Esempio n. 1
0
    def test_queryset_excludes_when_appropriate(self):
        # Add a draft post...
        draft_post = PostFactory.create(online=False, date=now() + timedelta(days=2))

        # ...and a future one...
        future_post = PostFactory.create(online=True, date=now() + timedelta(days=2))

        # ...and one that is live now.
        published_post = PostFactory.create(online=True)

        # We're not logged in, so we should only see the live post.
        response = self.client.get(reverse('posts:post_list'))
        self.assertEqual(len(response.context_data['object_list']), 1)

        # Check the detail views as well. Published ones should work:
        response = self.client.get(reverse('posts:post_detail', kwargs={'slug': published_post.slug, 'identifier': published_post.identifier}))
        self.assertEqual(response.status_code, 200)
        # But unpublished ones should not.
        for post in [draft_post, future_post]:
            response = self.client.get(reverse('posts:post_detail', kwargs={'slug': post.slug, 'identifier': post.identifier}))
            self.assertEqual(response.status_code, 404)

        # Now create a staff user and log in to it.
        get_user_model().objects.create_superuser(username='******', email='*****@*****.**', password='******')
        self.client.login(username='******', password='******')
        # When we're logged in we should see all of the draft posts.
        response = self.client.get(reverse('posts:post_list'))
        self.assertEqual(len(response.context_data['object_list']), 3)

        # And so should their detail views.
        for post in [draft_post, future_post, published_post]:
            response = self.client.get(reverse('posts:post_detail', kwargs={'slug': post.slug, 'identifier': post.identifier}))
            self.assertEqual(response.status_code, 200)
Esempio n. 2
0
    def test_posts_sitemap(self):
        PostFactory.create_batch(5, online=True)

        # Check that offline ones aren't being shown.
        PostFactory.create(online=False, date=now() - timedelta(minutes=1))

        # ...and ones with a future publication date.
        PostFactory.create(online=True, date=now() + timedelta(days=1))

        response = self.client.get(
            reverse('django.contrib.sitemaps.views.sitemap'))
        self.assertEqual(response.status_code, 200)

        tree = ElementTree.fromstring(response.content.decode('utf-8'))
        self.assertEqual(len(list(tree)), 5)
Esempio n. 3
0
    def test_post_detail_template_branches(self):
        # Ensure various branches in the post detail templates are tested.
        #
        # Test the "post has an image" branch of post_body.html
        post = PostFactory.create(image='large-image.jpg', online=True)
        response = self.client.get(post.get_absolute_url())
        self.assertEqual(response.status_code, 200)
        soup = BeautifulSoup(response.content, features='html.parser')
        self.assertEqual(len(soup.select('.post__image-wrapper')), 1)

        # Test the "has meta description" branch of post_detail.html
        post = PostFactory.create(meta_description='Meta description', online=True)
        response = self.client.get(post.get_absolute_url())
        self.assertEqual(response.status_code, 200)
        soup = BeautifulSoup(response.content, features='html.parser')
        self.assertEqual(soup.find('meta', attrs={'name': 'description'})['content'], 'Meta description')
Esempio n. 4
0
    def test_category_feed_view(self):
        category = CategoryFactory.create()
        post = PostFactory.create(online=True)
        post.categories.add(category)

        # Check queryset exclusion for other categories...
        PostFactory.create_batch(2, online=True)
        # ...and ensure that offline posts are being excluded.
        offline_post = PostFactory.create(online=False)
        offline_post.categories.add(category.pk)

        response = self.client.get(reverse('posts:post_category_feed', kwargs={'category': category.slug}))

        self.assertEqual(response.status_code, 200)
        self.assertEqual(list(response.context_data['object_list']), [post])
        self._rss_response_is_sane(response, expected_item_count=1)
Esempio n. 5
0
    def test_post_status_text(self):
        # If `online` is false, it should always show as "Draft"
        post = PostFactory.create(online=False)
        self.assertEqual(post.status_text, 'Draft')

        # ...even if the publication date is a future date (when online=True
        # it'll be "Scheduled").
        post = PostFactory.create(online=False, date=now() + timedelta(days=2))
        self.assertEqual(post.status_text, 'Draft')

        # Check future-scheduled posts.
        post = PostFactory.create(online=True, date=now() + timedelta(days=2))
        self.assertEqual(post.status_text, 'Scheduled')

        # And one that is live now.
        post = PostFactory.create(online=True)
        self.assertEqual(post.status_text, 'Published')
Esempio n. 6
0
    def test_category_view(self):
        category = CategoryFactory.create(meta_description='Test!', description='Test')
        post = PostFactory.create(online=True)
        post.categories.add(category)

        # create another uncategorised post
        other_post = PostFactory.create(online=True)

        response = self.client.get(reverse('posts:post_category_list', kwargs={'category': category.slug}))
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.context_data['object'], category)
        self.assertNotIn(other_post, response.context_data['object_list'])

        # Ensure that the "has SEO title" branch is checked in the template.
        category.seo_title = 'Search engine optimised!'
        category.save()
        response = self.client.get(reverse('posts:post_category_list', kwargs={'category': category.slug}))
        self.assertEqual(response.status_code, 200)
Esempio n. 7
0
    def test_detail_redirects(self):
        post_with_slug = PostFactory.create(slug='slug', online=True)

        post_without_slug = PostFactory.create(slug='', online=True)

        possibles = [
            # Post with slug called with identifier argument only should redirect.
            reverse('posts:post_detail', kwargs={'identifier': post_with_slug.identifier}),
            # Rewrite garbage in the slug.
            reverse('posts:post_detail', kwargs={'identifier': post_with_slug.identifier, 'slug': 'some-garbage-value'})
        ]
        for path in possibles:
            response = self.client.get(path)
            self.assertRedirects(response, post_with_slug.get_absolute_url(), status_code=301, target_status_code=200)

        # Test that putting a slug after the identifier argument on a post without a
        # slug redirects.
        response = self.client.get(reverse('posts:post_detail', kwargs={'identifier': post_without_slug.identifier, 'slug': 'anything-at-all'}))
        self.assertRedirects(response, post_without_slug.get_absolute_url(), status_code=301, target_status_code=200)
Esempio n. 8
0
    def test_post_str(self):
        post = PostFactory.create(title='Testing!', online=True)
        self.assertEqual(str(post), 'Testing!')

        post = PostFactory.create(title='', text='Body', online=True)
        self.assertEqual(str(post), 'Body')

        # Test body truncation.
        post = PostFactory.create(title='', text='a' * 41, online=True)
        self.assertEqual(str(post), ('a' * 38) + '...')

        post = PostFactory.create(title='', text='', online=True)
        self.assertEqual(str(post), '(Broken post)')

        # Check with a "real" image. The real tests are already done for
        # render_multiformat_image. We'll only make sure it looks something
        # like what we expect.
        post = PostFactory.create(title='',
                                  text='',
                                  online=True,
                                  image='small-image.jpg')

        self.assertIs(str(post).startswith('Image post: small-image'), True)
        self.assertIs(str(post).endswith('.jpg'), True)
Esempio n. 9
0
    def test_categories_sitemap(self):
        # Ensure unused categories are not shown in the sitemap, which
        # includes those that are only assigned to a post that is offline.
        used_category, unused_category, unused_category_2 = CategoryFactory.create_batch(
            3)

        post = PostFactory.create(online=True)
        post.categories.set([used_category])

        offline_post = PostFactory.create(online=False)
        offline_post.categories.set([unused_category_2])

        response = self.client.get(
            reverse('django.contrib.sitemaps.views.sitemap'))
        self.assertEqual(response.status_code, 200)

        tree = ElementTree.fromstring(response.content.decode('utf-8'))
        child_items = list(tree)
        self.assertEqual(len(child_items), 2)
        nsinfo = {'sitemaps': 'http://www.sitemaps.org/schemas/sitemap/0.9'}

        for obj in [post, used_category]:
            self.assertEqual(
                len([
                    True for child in child_items
                    if child.find('sitemaps:loc', nsinfo).text ==
                    f'http://testserver{obj.get_absolute_url()}'
                ]), 1)

        for obj in [unused_category, unused_category_2]:
            self.assertEqual(
                len([
                    True for child in child_items
                    if child.find('sitemaps:loc', nsinfo).text ==
                    f'http://testserver{obj.get_absolute_url()}'
                ]), 0)
Esempio n. 10
0
 def test_rss_html(self):
     # Ensure that all tags are being converted for use in RSS
     # appropriately.
     post = PostFactory.create(
         text='\n'.join([
             '<img src="/some-image/">', '<picture>',
             ' <source src="/another-image/">', '</picture>',
             '<a href="/boat/">boat</a>',
             '<div class="image__padder"></div>',
             '<div class="image" style="max-width: 100px"></div>'
         ]),
         online=True,
     )
     soup = BeautifulSoup(rss_post_body(post), 'html.parser')
     self.assertEqual(
         soup.find('img')['src'], 'https://example.com/some-image/')
     self.assertEqual(soup.find('a')['href'], 'https://example.com/boat/')
     self.assertEqual(
         soup.find('picture').find('source')['src'],
         'https://example.com/another-image/')
     self.assertIs(soup.find('div', attrs={'class': 'image__padder'}), None)
     self.assertEqual(
         soup.find('div', attrs={'class': 'image'})['style'], '')
Esempio n. 11
0
    def test_quality_control_filter(self):
        # Ensure QualityControlListFilter works.
        cat = CategoryFactory.create()

        PostFactory.create(meta_description='test',
                           online=True,
                           categories=[cat])

        no_meta_post = PostFactory.create(online=True, categories=[cat])

        no_categories_post = PostFactory.create(meta_description='test',
                                                online=True)

        no_alt_text_post = PostFactory.create(
            title='No alt text',
            slug='no-alt-text',
            meta_description='Description',
            image='small-image.jpg',
            online=True,
        )
        no_alt_text_post.categories.set([cat])

        no_alt_text_in_body_post = PostFactory.create(
            meta_description='test',
            text='![](/some-image.jpg)',
            online=True,
        )
        no_alt_text_in_body_post.categories.set([cat])

        admin_url = reverse('admin:posts_post_changelist')
        response = self.client.get(admin_url)
        # sanity check
        self.assertEqual(len(response.context_data['cl'].result_list), 5)

        response = self.client.get(admin_url,
                                   {'quality_control': 'no_meta_description'})
        results = response.context_data['cl'].result_list
        self.assertEqual(len(results), 1)
        self.assertEqual(results[0], no_meta_post)

        response = self.client.get(admin_url,
                                   {'quality_control': 'no_categories'})
        results = response.context_data['cl'].result_list
        self.assertEqual(len(results), 1)
        self.assertEqual(results[0], no_categories_post)

        response = self.client.get(admin_url,
                                   {'quality_control': 'no_alt_text'})
        self.assertEqual(response.status_code, 200)
        results = response.context_data['cl'].result_list
        self.assertEqual(len(results), 1)
        self.assertEqual(results[0], no_alt_text_post)

        response = self.client.get(admin_url,
                                   {'quality_control': 'no_alt_text_body'})
        self.assertEqual(response.status_code, 200)
        results = response.context_data['cl'].result_list
        self.assertEqual(len(results), 1)
        self.assertEqual(results[0], no_alt_text_in_body_post)

        # Check the fall-through case, just to ensure full coverage.
        response = self.client.get(admin_url, {'quality_control': 'garbage'})
        self.assertEqual(len(response.context_data['cl'].result_list), 5)
Esempio n. 12
0
    def test_post_get_title_link_url(self):
        post = PostFactory.create(online=True)
        self.assertEqual(post.get_title_link_url(), post.get_absolute_url())

        post = PostFactory.create(link='https://example.invalid', online=True)
        self.assertEqual(post.get_title_link_url(), 'https://example.invalid')