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
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
):
37 User
= get_user_model()
38 self
.user
= User(username
="web-test", email
="web-test@example.com")
39 self
.user
.set_password("pwd")
42 self
.auth_string
= create_auth_string("test", "pwd")
45 def tearDownClass(self
):
48 def test_access_parameterless_pages(self
):
69 self
.access_pages(pages
, [], True)
71 def test_access_podcast_pages(self
):
74 def access_pages(self
, pages
, args
, login
):
77 "/login/", dict(login_username
=self
.user
.username
, pwd
="pwd")
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"""
89 # create a podcast and some episodes
90 podcast
= Podcast
.objects
.create(
91 id=uuid
.uuid1(), title
="My Podcast", max_episode_order
=1
94 episode
= Episode
.objects
.get_or_create_for_url(
95 podcast
, "http://www.example.com/episode%d.mp3" % (n
,)
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):
115 def test_episode_queries(self
):
116 """Test that the expected number of queries is executed"""
118 "episode-slug", args
=(self
.podcast_slug
.slug
, self
.episode_slug
.slug
)
121 with self
.assertNumQueries(5):
125 class PodcastLogoTests(TestCase
):
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()
135 self
.podcast
.delete()
137 def _save_logo(self
):
138 with responses
.RequestsMock() as rsps
, open(IMG_PATH1
, "rb") as body
:
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
)
158 def test_save_logo(self
):
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
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"""
190 CoverArt
.save_podcast_logo(None)
193 "CoverArt.save_podcast_logo(None) should not raise " "an exception"
196 def test_exception_during_fetch(self
):
197 with responses
.RequestsMock() as rsps
:
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
):
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(
227 ) as body2
, open(IMG_PATH2
, "rb") as body3
:
233 content_type
="image/png",
240 content_type
="image/png",
247 content_type
="image/png",
250 logo_url
= get_logo_url(self
.podcast
, 32)
253 CoverArt
.save_podcast_logo(self
.URL
)
254 response1
= self
._fetch
_cover
(self
.podcast
)
257 CoverArt
.save_podcast_logo(self
.URL
)
258 response2
= self
._fetch
_cover
(self
.podcast
)
261 list(response1
.streaming_content
), list(response2
.streaming_content
)
265 CoverArt
.save_podcast_logo(self
.URL
)
266 response3
= self
._fetch
_cover
(self
.podcast
)
269 list(response2
.streaming_content
), list(response3
.streaming_content
)
273 class PublisherPageTests(TestCase
):
274 """Test the publisher page"""
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
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"
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"
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
)