Merge pull request #793 from gpodder/remove-advertise
[mygpo.git] / mygpo / web / tests.py
blob10277dfa0250ab78cbeb2f4ebe7d1cbe728c5974
1 import unittest
2 import doctest
3 import uuid
4 import os.path
6 import requests
7 import responses
9 from django.conf import settings
10 from django.test import TestCase, Client, override_settings
11 from django.urls import reverse
12 from django.core.files.storage import FileSystemStorage
13 from django.contrib.auth import get_user_model
15 from mygpo.podcasts.models import Podcast, Episode, Slug
16 import mygpo.web.utils
17 from mygpo.web.logo import CoverArt, get_logo_url
18 from mygpo.test import create_auth_string, anon_request
20 import logging
22 logger = logging.getLogger(__name__)
25 IMG_PATH1 = os.path.abspath(
26 os.path.join(settings.BASE_DIR, "..", "res", "gpoddernet_228.png")
29 IMG_PATH2 = os.path.abspath(
30 os.path.join(settings.BASE_DIR, "..", "res", "gpoddernet_16.png")
34 class SimpleWebTests(TestCase):
35 @classmethod
36 def setUpClass(self):
37 User = get_user_model()
38 self.user = User(username="web-test", email="web-test@example.com")
39 self.user.set_password("pwd")
40 self.user.save()
42 self.auth_string = create_auth_string("test", "pwd")
44 @classmethod
45 def tearDownClass(self):
46 self.user.delete()
48 def test_access_parameterless_pages(self):
49 pages = [
50 "history",
51 "suggestions",
52 "tags",
53 "subscriptions",
54 "subscriptions-opml",
55 "favorites",
56 "account",
57 "privacy",
58 "delete-account",
59 "share",
60 "toplist",
61 "episode-toplist",
62 "devices",
63 "device-create",
64 "login",
65 "logout",
66 "home",
69 self.access_pages(pages, [], True)
71 def test_access_podcast_pages(self):
72 pages = ["podcast"]
74 def access_pages(self, pages, args, login):
75 if login:
76 self.client.post(
77 "/login/", dict(login_username=self.user.username, pwd="pwd")
80 for page in pages:
81 response = self.client.get(reverse(page, args=args), follow=True)
82 self.assertEqual(response.status_code, 200)
85 class PodcastPageTests(TestCase):
86 """Test the podcast page"""
88 def setUp(self):
89 # create a podcast and some episodes
90 podcast = Podcast.objects.create(
91 id=uuid.uuid1(), title="My Podcast", max_episode_order=1
93 for n in range(20):
94 episode = Episode.objects.get_or_create_for_url(
95 podcast, "http://www.example.com/episode%d.mp3" % (n,)
96 ).object
98 # we only need (the last) one
99 self.episode_slug = Slug.objects.create(
100 content_object=episode, order=0, scope=podcast.as_scope, slug=str(n)
103 self.podcast_slug = Slug.objects.create(
104 content_object=podcast, order=n, scope=podcast.scope, slug="podcast"
107 def test_podcast_queries(self):
108 """Test that the expected number of queries is executed"""
109 url = reverse("podcast-slug", args=(self.podcast_slug.slug,))
110 # the number of queries must be independent of the number of episodes
112 with self.assertNumQueries(5):
113 anon_request(url)
115 def test_episode_queries(self):
116 """Test that the expected number of queries is executed"""
117 url = reverse(
118 "episode-slug", args=(self.podcast_slug.slug, self.episode_slug.slug)
121 with self.assertNumQueries(5):
122 anon_request(url)
125 class PodcastLogoTests(TestCase):
126 def setUp(self):
127 # create a podcast
128 self.URL = "http://example.com/{}.png".format(uuid.uuid1().hex)
129 self.podcast = Podcast.objects.create(
130 id=uuid.uuid1(), title="My Podcast", max_episode_order=1, logo_url=self.URL
132 self.client = Client()
134 def tearDown(self):
135 self.podcast.delete()
137 def _save_logo(self):
138 with responses.RequestsMock() as rsps, open(IMG_PATH1, "rb") as body:
139 rsps.add(
140 responses.GET, self.URL, status=200, body=body, content_type="image/png"
143 CoverArt.save_podcast_logo(self.URL)
145 def _fetch_cover(self, podcast, size=32):
146 logo_url = get_logo_url(podcast, size)
148 response = self.client.get(logo_url)
149 self.assertEqual(302, response.status_code)
150 redir = response["Location"]
152 logger.warning("Redirecting to {}".format(redir))
154 response = self.client.get(redir)
155 self.assertEqual(200, response.status_code)
156 return response
158 def test_save_logo(self):
159 self._save_logo()
160 self._fetch_cover(self.podcast)
162 def test_get_nonexisting(self):
163 URL = "http://example.com/non-existing-logo.png"
165 self.podcast.logo_url = URL
167 logo_url = get_logo_url(self.podcast, 32)
169 response = self.client.get(logo_url)
170 self.assertEqual(404, response.status_code)
172 def test_get_existing_thumbnail(self):
173 """Retrieve an already existing thumbnail
175 No distinction is visible outside, but it covers different
176 code paths"""
178 self._save_logo()
179 logo_url = get_logo_url(self.podcast, 32)
181 response = self.client.get(logo_url)
182 self.assertEqual(302, response.status_code, response.content)
184 response = self.client.get(logo_url)
185 self.assertEqual(302, response.status_code, response.content)
187 def test_save_empty_logo(self):
188 """Make sure that save_podcast_logo(None) does not fail"""
189 try:
190 CoverArt.save_podcast_logo(None)
191 except:
192 self.fail(
193 "CoverArt.save_podcast_logo(None) should not raise " "an exception"
196 def test_exception_during_fetch(self):
197 with responses.RequestsMock() as rsps:
198 rsps.add(
199 responses.GET,
200 self.URL,
201 body=requests.exceptions.RequestException("Fetching URL failed"),
204 CoverArt.save_podcast_logo(self.URL)
206 def test_error_open_file(self):
207 class ErrFileSystemStorage(FileSystemStorage):
208 def open(*args, **kwargs):
209 raise IOError
211 self._save_logo()
212 from mygpo.web import logo
214 _logo_storage = logo.LOGO_STORAGE
215 logo.LOGO_STORAGE = ErrFileSystemStorage(location=settings.MEDIA_ROOT)
217 logo_url = get_logo_url(self.podcast, 32)
219 response = self.client.get(logo_url)
220 self.assertEqual(404, response.status_code)
222 logo.LOGO_STORAGE = _logo_storage
224 def test_new_logo(self):
225 with responses.RequestsMock() as rsps, open(IMG_PATH1, "rb") as body1, open(
226 IMG_PATH1, "rb"
227 ) as body2, open(IMG_PATH2, "rb") as body3:
228 rsps.add(
229 responses.GET,
230 self.URL,
231 status=200,
232 body=body1,
233 content_type="image/png",
235 rsps.add(
236 responses.GET,
237 self.URL,
238 status=200,
239 body=body2,
240 content_type="image/png",
242 rsps.add(
243 responses.GET,
244 self.URL,
245 status=200,
246 body=body3,
247 content_type="image/png",
250 logo_url = get_logo_url(self.podcast, 32)
252 # first request
253 CoverArt.save_podcast_logo(self.URL)
254 response1 = self._fetch_cover(self.podcast)
256 # stayed the same
257 CoverArt.save_podcast_logo(self.URL)
258 response2 = self._fetch_cover(self.podcast)
260 self.assertEqual(
261 list(response1.streaming_content), list(response2.streaming_content)
264 # changed
265 CoverArt.save_podcast_logo(self.URL)
266 response3 = self._fetch_cover(self.podcast)
268 self.assertNotEqual(
269 list(response2.streaming_content), list(response3.streaming_content)
273 class PublisherPageTests(TestCase):
274 """Test the publisher page"""
276 @classmethod
277 def setUpTestData(self):
278 User = get_user_model()
279 self.user = User(username="web-test", email="web-test@example.com")
280 self.user.set_password("pwd")
281 self.user.is_staff = True
282 self.user.save()
284 def test_publisher_detail_slug(self):
285 # create a podcast with slug
286 podcast = Podcast.objects.get_or_create_for_url(
287 "http://example.com/podcast.rss"
288 ).object
289 slug = "test"
290 podcast.set_slug(slug)
292 url = reverse("podcast-publisher-detail-slug", args=(slug,))
294 self.client.login(username="web-test", password="pwd")
296 response = self.client.get(url)
297 self.assertEqual(200, response.status_code)
299 def test_publisher_detail_id(self):
300 # create a podcast with no slug
301 podcast = Podcast.objects.get_or_create_for_url(
302 "http://example.com/podcast2.rss"
303 ).object
305 url = reverse("podcast-publisher-detail-id", args=(podcast.id,))
307 self.client.login(username="web-test", password="pwd")
309 response = self.client.get(url)
310 self.assertEqual(200, response.status_code)