def test_get_recent_comments(): PostFactory.create_batch(10, published=True) for post in Post.objects.all(): CommentFactory.create_batch(3, post=post) # Generate 30 comments in system, but request back only n through the template tag. recent = get_recent_comments(10) assert len(recent['comments']) == 10 recent = get_recent_comments(7) assert len(recent['comments']) == 7 # Check object type of first element in return list assert isinstance(recent['comments'][0], Comment)
def test_threaded_comments(): # Methods on Post and Comment let us get all top-level comments for a Post, # and get child comments of a comment. Create 5 top-level comments, then 3 child comments # of the last comment. Check numbers. p = PostFactory() CommentFactory.create_batch(5, post=p) assert p.top_level_comments().count() == 5 last_comment = p.top_level_comments().last() CommentFactory.create_batch(3, post=p, parent=last_comment) assert last_comment.child_comments().count() == 3 # Now check again - count of top-level should still be 5, even though we've added more comments to the Post. assert p.top_level_comments().count() == 5
def test_send_comment_moderation_email(email_backend_setup, admin_user): """Email should be sent with a different subject and body depending on whether it needs moderation.""" site_title = "foobar blog" site_url = "http://example.com" comment_body = "hello world" from_email = "*****@*****.**" moderation_email = "*****@*****.**" ConfigFactory(site_url=site_url, site_title=site_title, from_email=from_email, moderation_email=moderation_email) post = PostFactory(author=admin_user) # Test spam first comment = CommentFactory(body=comment_body, post=post, spam=True, approved=False) send_comment_moderation_email(comment) sent_msg = mail.outbox[0] path = reverse('tangerine:manage_comment', kwargs={'comment_id': comment.id}) assert len(mail.outbox) == 1 assert sent_msg.subject == "A new comment on {} requires moderation".format(site_title) assert comment_body in sent_msg.body # Content is wrapped in email template, so not identical assert "{}{}".format(site_url, path) in sent_msg.body # Email includes comment moderation link assert sent_msg.from_email == from_email assert moderation_email in sent_msg.recipients() # Then ham comment = CommentFactory(body=comment_body, post=post, spam=False, approved=True) send_comment_moderation_email(comment) sent_msg = mail.outbox[1] assert sent_msg.subject == "A new comment on {} has been automatically published".format(site_title)
def test_post_in_multiple_cats(): cat1 = CategoryFactory(title="Foo") cat2 = CategoryFactory(title="Bar") post = PostFactory() post.categories.add(cat1) post.categories.add(cat2) assert post.categories.all().count() == 2
def test_unapproved_comments_not_in_qs(cats_and_posts): # Tests CommentManager post = PostFactory() CommentFactory.create_batch(5, post=post) CommentFactory.create_batch(3, post=post, approved=False) assert Comment.objects.all().count() == 8 assert Comment.pub.all().count() == 5
def test_comment_factory(): p = PostFactory() comment = CommentFactory.create(post=p) assert isinstance(comment, Comment) assert len(comment.name) > 3 assert comment.website.startswith('http') assert '@' in comment.email
def test_post_factory(make_cats): post = PostFactory(title="Space and Drums") assert isinstance(post, Post) assert len(post.content) > 5 assert len(post.summary) > 5 assert post.slug == 'space-and-drums' assert post.tags.count() > 0 assert isinstance(post.created, datetime)
def test_submit_aksimet_spam(): """Akismet API will believe what we tell it (return True if we say it's spam and vice versa). So simple check.""" if hasattr(settings, 'AKISMET_KEY'): ConfigFactory(akismet_key=settings.AKISMET_KEY, site_url=settings.SITE_URL) post = PostFactory() c1 = CommentFactory(post=post, email='*****@*****.**', spam=True) assert akismet_spam_ham(c1) is True
def create_cats_posts_comments(blog, cats): # Given a Blog object and a list of category titles, generate Categories full of Posts with Comments. for cat_title in cats: cat = CategoryFactory.create(blog=blog, title=cat_title) for _ in range(5): p = PostFactory(blog=blog, author=author) p.categories.add(cat) CommentFactory.create_batch(random.randint(0, 10), post=p) print( "Fake posts and comments in blog \"{}\" created (category \"{}\")" .format(blog.title, cat_title))
def test_get_search_qs(): # Test reusable queryset generator for Post search terms post1 = PostFactory(title="Send in the clowns") post2 = PostFactory(content="China Grove back in the news") post3 = PostFactory(summary="Clowns to the left of me, jokers to the right...") results = get_search_qs("clowns") assert len(results) == 2 assert post1 in results assert post2 not in results assert post3 in results # Test case insensitivity results = get_search_qs("Clowns") assert len(results) == 2 results = get_search_qs("CLOWNS") assert len(results) == 2 results = get_search_qs("left") assert len(results) == 1
def test_all_hours_in_24(config, client, settings, hours, tz_settings): """ Use parameterized fixtures to test posts made in all 24 hours in a day, ensuring that URL still resolves whether host project is TZ aware or not (test both with `USE_TZ = True` and `USE_TZ = False`). We want to prove that we don't slip over the date boundary no matter what time of day we post, thus changing the URL and generating 404s. We want to test not just that all date URLs resolve, but that all 24 URLs are identical. Due to paramaterization, this test runs itself 48 times! """ # First two statements use parameterized fixtures (tz_settings and hours) settings.USE_TZ = tz_settings ref_pub_date = datetime.datetime.strptime( '{} {} {} {} {} {}'.format(2018, 2, 2, hours, 3, 3), '%Y %m %d %H %M %S') hourly_post = PostFactory(slug="somepost", pub_date=make_aware(ref_pub_date)) assert "2018/2/2" in hourly_post.get_absolute_url() url = hourly_post.get_absolute_url() response = client.get(url) assert response.status_code == 200
def test_tag_view(config, client): p = PostFactory() p.tags.add("python") # Access with a good tag, then with a bad tag url = reverse('tangerine:tag', kwargs={'tag_slug': 'python'}) response = client.get(url) assert response.status_code == 200 url = reverse('tangerine:tag', kwargs={'tag_slug': 'frisbee'}) response = client.get(url) assert response.status_code == 404
def test_future_posts(settings): # If `show_future` enabled in config, show Posts with future timestamps in calls to Post.pub.all(). # Exclude otherwise. Default for `show_future` is False. settings.USE_TZ = False config = ConfigFactory() past_pub_date = datetime.datetime.strptime( '{} {} {} {} {} {}'.format(2017, 2, 2, 3, 3, 3), '%Y %m %d %H %M %S') past_post = PostFactory(pub_date=make_aware(past_pub_date)) future_pub_date = datetime.datetime.strptime( '{} {} {} {} {} {}'.format(2037, 2, 2, 3, 3, 3), '%Y %m %d %H %M %S') future_post = PostFactory(pub_date=make_aware(future_pub_date)) # By default, should not include future_post assert past_post in Post.pub.all() assert future_post not in Post.pub.all() # If show_future enabled in config, DO show future_post in queries config.show_future = True config.save() assert future_post in Post.pub.all()
def test_get_date_archives_month(settings, tz_settings): '''See docstring for test_get_date_archives_year() above.''' settings.USE_TZ = tz_settings # Causes this test to run twice. for year in [2010, 2012, 2015, 2018, 2020]: # Creating groups of posts in 5 different years for month in [3, 6, 9]: # Creating posts for 3 different months in each year pub_date = datetime.datetime.strptime('{} {} {} {} {} {}'.format( year, month, 2, 3, 3, 3), '%Y %m %d %H %M %S') PostFactory(pub_date=make_aware(pub_date)) assert Post.objects.all().count() == 15 # Three posts in each of five years # Request dates excluding the first and last in list dates = get_date_archives(dtype='month', start='20120101', end='20181231') assert len(dates) == 9 # Three posts each in three years assert isinstance(dates[0], datetime.date)
def test_get_non_empty_categories(): # Don't show empty categories in template tag. It's OK for cats with unpublished or trashed posts # to be returned, unless they are the *only* post in the category. # Create good categories with published posts num_cats = 5 CategoryFactory.create_batch(num_cats) for c in Category.objects.all(): p = PostFactory(published=True, trashed=False) p.categories.add(c) # Make categories with both published/unpublished and trashed/untrashed posts has_trashed_cat = CategoryFactory() trashed_post = PostFactory(trashed=True) non_trashed_post = PostFactory(trashed=False) trashed_post.categories.add(has_trashed_cat) non_trashed_post.categories.add(has_trashed_cat) has_unpub_cat = CategoryFactory() unpub_post = PostFactory(published=False) pub_post = PostFactory(published=True) unpub_post.categories.add(has_unpub_cat) pub_post.categories.add(has_unpub_cat) empty_cat = CategoryFactory() # Number of cats found by template tag should now be 7 since these cats have both published and untrashed posts. cats = get_categories() assert isinstance(cats, dict) assert len(cats.get('categories')) == 7 # Create cats with *only* unpub or trashed posts has_only_trashed_cat = CategoryFactory() trashed_post = PostFactory(trashed=True) trashed_post.categories.add(has_only_trashed_cat) has_only_unpub_cat = CategoryFactory() unpub_post = PostFactory(published=False) unpub_post.categories.add(has_only_unpub_cat) # Number of cats found by template tag should *still* be 7 cats = get_categories() assert len(cats.get('categories')) == 7 # Final reckoning goodcats = cats.get('categories') assert has_trashed_cat in goodcats assert has_unpub_cat in goodcats assert has_only_trashed_cat not in goodcats assert has_only_unpub_cat not in goodcats assert empty_cat not in goodcats
def test_get_date_archives_year(settings, tz_settings): '''get_date_archives() template tag returns a set of dates for which posts exist. Takes `dtype='year'` to only return years, or `dtype='month'` to only return months. Takes start and end dates as strings. Create posts in a list of years, check for length of return, and instance type of one of the results. Use paramaterized settings toggle to test that it works whether timezone awareness is on or off in containing site.''' settings.USE_TZ = tz_settings # Causes this test to run twice. for year in [2007, 2008, 2010, 2012, 2015, 2018, 2020]: # Creating posts in 7 different years pub_date = datetime.datetime.strptime('{} {} {} {} {} {}'.format(year, 2, 2, 3, 3, 3), '%Y %m %d %H %M %S') PostFactory(pub_date=make_aware(pub_date)) assert Post.objects.all().count() == 7 # # Three posts each in five years # Request dates excluding the first and last in list dates = get_date_archives(dtype='year', start='20080101', end='20181231') assert len(dates) == 5 assert isinstance(dates[0], datetime.date)
def test_spam_check(): """For now we are just testing our route to the Akismet API and whether we store submitted comments as spam or not. Later expand this into multiple tests to support multiple spam checking engines. Devs who want to run this test *must* add to their *test* settings: AKISMET_KEY = 'abc123' and SITE_URL = 'https://your.registered.domain' (but with real values). Otherwise we can't run tests that call their API with YOUR credentials. See https://akismet.com/development/api/#detailed-docs for notes on testing Akismet API calls.""" if hasattr(settings, 'AKISMET_KEY'): ConfigFactory(akismet_key=settings.AKISMET_KEY, site_url=settings.SITE_URL) post = PostFactory() # Good comment: c1 = CommentFactory(post=post, email='*****@*****.**') c2 = CommentFactory(post=post) assert spam_check(c1) is True assert spam_check(c2) is False
def test_approval_toggle(): config = ConfigFactory() # auto_approve defaults to True post = PostFactory() c1 = CommentFactory(post=post, approved=False) assert not c1.approved assert not ApprovedCommentor.objects.filter(email=c1.email).exists() toggle_approval(c1) assert c1.approved assert ApprovedCommentor.objects.filter(email=c1.email).exists() # With auto_approve disabled, state is toggled but commenter is never in ApprovedCommentors config.auto_approve_previous_commentors = False config.save() c2 = CommentFactory(post=post, approved=False) assert not c2.approved assert not ApprovedCommentor.objects.filter(email=c2.email).exists() toggle_approval(c2) assert c2.approved assert not ApprovedCommentor.objects.filter(email=c2.email).exists()
def cats_and_posts(): PostFactory.create_batch(30)
def test_trashed_post_not_in_qs(cats_and_posts): somepost = PostFactory(trashed=True) qs = Post.pub.all() assert somepost not in qs
def test_unpublished_post_not_in_qs(cats_and_posts): somepost = PostFactory(published=False) qs = Post.pub.all() assert somepost not in qs
def cats_and_posts(): ConfigFactory() CategoryFactory.create_batch(10) PostFactory.create_batch(30)
def post1(): # Create post with category. post1 = PostFactory(slug="somepost") cat = CategoryFactory(slug="somecat") post1.categories.add(cat) return post1
def posts_with_comments(): PostFactory.create_batch(3) for p in Post.objects.all(): CommentFactory(post=p)