From 465e5933681975838a00c6c027967664d038d18e Mon Sep 17 00:00:00 2001 From: Sonny Bakker Date: Fri, 25 Sep 2020 22:34:56 +0200 Subject: [PATCH] Add TwitterTemplate view tests --- .../accounts/tests/test_integrations.py | 151 ++++++++++++++++++ src/newsreader/accounts/views/integrations.py | 25 ++- 2 files changed, 172 insertions(+), 4 deletions(-) diff --git a/src/newsreader/accounts/tests/test_integrations.py b/src/newsreader/accounts/tests/test_integrations.py index 5c65caf..cdc9546 100644 --- a/src/newsreader/accounts/tests/test_integrations.py +++ b/src/newsreader/accounts/tests/test_integrations.py @@ -5,6 +5,7 @@ from uuid import uuid4 from django.core.cache import cache from django.test import TestCase from django.urls import reverse +from django.utils.translation import gettext as _ from bs4 import BeautifulSoup @@ -384,3 +385,153 @@ class TwitterAuthRedirectViewTestCase(TestCase): self.assertIsNone(cached_token) self.assertIsNone(cached_secret) + + +class TwitterTemplateViewTestCase(TestCase): + def setUp(self): + self.user = UserFactory(email="test@test.nl", password="test") + self.client.force_login(self.user) + + self.patch = patch("newsreader.accounts.views.integrations.post") + self.mocked_post = self.patch.start() + + def tearDown(self): + cache.clear() + + def test_simple(self): + cache.set_many( + { + f"twitter-{self.user.email}-token": "foo", + f"twitter-{self.user.email}-secret": "bar", + } + ) + + params = {"denied": "", "oauth_token": "foo", "oauth_verifier": "barfoo"} + + self.mocked_post.return_value = Mock( + text="oauth_token=realtoken&oauth_token_secret=realsecret" + ) + + response = self.client.get( + f"{reverse('accounts:twitter-template')}?{urlencode(params)}" + ) + + self.assertContains(response, _("Twitter account is linked")) + + self.user.refresh_from_db() + + self.assertEquals(self.user.twitter_oauth_token, "realtoken") + self.assertEquals(self.user.twitter_oauth_token_secret, "realsecret") + + self.assertIsNone(cache.get(f"twitter-{self.user.email}-token")) + self.assertIsNone(cache.get(f"twitter-{self.user.email}-secret")) + + def test_denied(self): + params = {"denied": "true", "oauth_token": "foo", "oauth_verifier": "barfoo"} + + response = self.client.get( + f"{reverse('accounts:twitter-template')}?{urlencode(params)}" + ) + + self.assertContains(response, _("Twitter authorization failed")) + + self.user.refresh_from_db() + + self.assertIsNone(self.user.twitter_oauth_token) + self.assertIsNone(self.user.twitter_oauth_token_secret) + + self.mocked_post.assert_not_called() + + def test_mismatched_token(self): + cache.set_many( + { + f"twitter-{self.user.email}-token": "foo", + f"twitter-{self.user.email}-secret": "bar", + } + ) + + params = {"denied": "", "oauth_token": "boo", "oauth_verifier": "barfoo"} + + response = self.client.get( + f"{reverse('accounts:twitter-template')}?{urlencode(params)}" + ) + + self.assertContains(response, _("OAuth tokens failed to match")) + + self.user.refresh_from_db() + + self.assertIsNone(self.user.twitter_oauth_token) + self.assertIsNone(self.user.twitter_oauth_token_secret) + + self.mocked_post.assert_not_called() + + def test_missing_secret(self): + cache.set_many({f"twitter-{self.user.email}-token": "foo"}) + + params = {"denied": "", "oauth_token": "foo", "oauth_verifier": "barfoo"} + + response = self.client.get( + f"{reverse('accounts:twitter-template')}?{urlencode(params)}" + ) + + self.assertContains(response, _("No matching tokens found for this user")) + + self.user.refresh_from_db() + + self.assertIsNone(self.user.twitter_oauth_token_secret) + + self.mocked_post.assert_not_called() + + def test_stream_exception(self): + cache.set_many( + { + f"twitter-{self.user.email}-token": "foo", + f"twitter-{self.user.email}-secret": "bar", + } + ) + + params = {"denied": "", "oauth_token": "foo", "oauth_verifier": "barfoo"} + + self.mocked_post.side_effect = StreamException + + response = self.client.get( + f"{reverse('accounts:twitter-template')}?{urlencode(params)}" + ) + + self.assertContains(response, _("Failed requesting access token")) + + self.user.refresh_from_db() + + self.assertIsNone(self.user.twitter_oauth_token) + self.assertIsNone(self.user.twitter_oauth_token_secret) + + self.assertIsNotNone(cache.get(f"twitter-{self.user.email}-token")) + self.assertIsNotNone(cache.get(f"twitter-{self.user.email}-secret")) + + def test_unexpected_contents(self): + cache.set_many( + { + f"twitter-{self.user.email}-token": "foo", + f"twitter-{self.user.email}-secret": "bar", + } + ) + + params = {"denied": "", "oauth_token": "foo", "oauth_verifier": "barfoo"} + + self.mocked_post.return_value = Mock( + text="foobar=boo&oauth_token_secret=realsecret" + ) + + response = self.client.get( + f"{reverse('accounts:twitter-template')}?{urlencode(params)}" + ) + + self.assertContains(response, _("No credentials found in Twitter response")) + + self.user.refresh_from_db() + + self.assertIsNone(self.user.twitter_oauth_token) + self.assertIsNone(self.user.twitter_oauth_token_secret) + + self.assertIsNotNone(cache.get(f"twitter-{self.user.email}-token")) + self.assertIsNotNone(cache.get(f"twitter-{self.user.email}-secret")) diff --git a/src/newsreader/accounts/views/integrations.py b/src/newsreader/accounts/views/integrations.py index a146bda..1b25ab8 100644 --- a/src/newsreader/accounts/views/integrations.py +++ b/src/newsreader/accounts/views/integrations.py @@ -246,8 +246,6 @@ class TwitterAuthRedirectView(RedirectView): return redirect(f"{TWITTER_AUTH_URL}/?{request_params}") -# TODO remove cached tokens -# TODO write tests class TwitterTemplateView(TemplateView): template_name = "accounts/views/twitter.html" @@ -311,11 +309,30 @@ class TwitterTemplateView(TemplateView): ) params = parse_qs(response.text) - oauth_token = params.get("oauth_token")[0] - oauth_secret = params.get("oauth_token_secret")[0] + + try: + oauth_token = params["oauth_token"][0] + oauth_secret = params["oauth_token_secret"][0] + except KeyError: + logger.exception("No credentials in Twitter response") + + return self.render_to_response( + { + **context, + "error": _("No credentials found in Twitter response"), + "authorized": False, + } + ) request.user.twitter_oauth_token = oauth_token request.user.twitter_oauth_token_secret = oauth_secret request.user.save() + cache.delete_many( + [ + f"twitter-{request.user.email}-token", + f"twitter-{request.user.email}-secret", + ] + ) + return self.render_to_response({**context, "error": None, "authorized": True})