import json from django.contrib.auth.models import User from django.test import TestCase from django.utils import timezone from feeds.models import Item, Source from .models import EpisodeArticle, PodcastEpisode, PodcastFeed, TranscriptionJob BODY = ('
Zusammenfassung
▶ ab 12:34 und Quelle
') class ArticleTests(TestCase): def setUp(self): self.user = User.objects.create_user(username='alice', password='pw12345678') self.client.force_login(self.user) self.feed = PodcastFeed.objects.create(user=self.user, rss_url='https://p.example/rss', title='Salon', author='Anna Autorin', artwork_url='https://p.example/feed.jpg') self.ep = PodcastEpisode.objects.create(feed=self.feed, guid='e1', title='Folge 1', audio_url='https://p.example/e1.mp3', artwork_url='https://p.example/e1.jpg') def url(self, ep=None): return f'/podcasts/episodes/{(ep or self.ep).id}/article/' def post(self, data=None, ep=None): data = {'title': 'Ein Artikel', 'summary': 'Kurz.', 'body_html': BODY, 'model': 'claude', 'kind': 'Interview'} \ if data is None else data return self.client.post(self.url(ep), json.dumps(data), content_type='application/json') def test_requires_login_and_ownership(self): self.client.logout() self.assertEqual(self.post().status_code, 401) self.assertEqual(self.client.delete(self.url()).status_code, 401) bob = User.objects.create_user(username='bob', password='pw12345678') self.client.force_login(bob) self.assertEqual(self.post().status_code, 404) self.assertEqual(self.client.delete(self.url()).status_code, 404) self.assertFalse(Item.objects.exists()) def test_create(self): r = self.post() self.assertEqual(r.status_code, 200) item = Item.objects.get(pk=r.json()['item_id']) self.assertEqual(item.user, self.user) self.assertEqual(item.kind, Source.BLOG) self.assertEqual(item.title, 'Ein Artikel') self.assertEqual(item.summary, 'Kurz.') self.assertEqual(item.author, 'Anna Autorin') self.assertEqual(item.image_url, 'https://p.example/e1.jpg') self.assertEqual(item.url, 'https://p.example/e1.mp3') self.assertTrue(item.content_full) self.assertGreater(item.words, 3) self.assertLess((timezone.now() - item.published).total_seconds(), 60) art = EpisodeArticle.objects.get(episode=self.ep) self.assertEqual((art.item, art.model, art.kind), (item, 'claude', 'Interview')) self.assertEqual(item.episode_article, art) def test_image_falls_back_to_feed_artwork(self): self.ep.artwork_url = '' self.ep.save() item = Item.objects.get(pk=self.post().json()['item_id']) self.assertEqual(item.image_url, 'https://p.example/feed.jpg') def test_sanitizer_keeps_time_links_only(self): item = Item.objects.get(pk=self.post().json()['item_id']) self.assertNotIn(''}, {'title': 'x', 'body_html': 'a' * 1_000_001}, {'title': 'x', 'body_html': BODY, 'model': 'm' * 101}): self.assertEqual(self.post(data).status_code, 400, data and list(data)) self.assertEqual(self.client.post(self.url(), 'nope', content_type='application/json').status_code, 400) self.assertFalse(Item.objects.exists()) self.assertEqual(self.client.get(self.url()).status_code, 405) def test_saving_clears_the_wish(self): TranscriptionJob.objects.create(episode=self.ep, state='done', want_article=True, claimed_by='phone', claimed_until=timezone.now() + timezone.timedelta(minutes=10)) self.post() job = TranscriptionJob.objects.get() self.assertEqual((job.want_article, job.claimed_by, job.claimed_until), (False, '', None)) def test_in_favourite_blogs_with_episode_id(self): item_id = self.post().json()['item_id'] items = self.client.get('/feeds/blogs/?fav=1').json()['items'] self.assertEqual([i['id'] for i in items], [item_id]) self.assertEqual(items[0]['episode_id'], self.ep.id) detail = self.client.get(f'/feeds/items/{item_id}/').json()['item'] self.assertEqual(detail['episode_id'], self.ep.id) self.assertIn('href="#t=754"', detail['content']) def test_ordinary_items_have_no_episode_id(self): src = Source.objects.create(user=self.user, url='https://b.example/feed', title='B', kind=Source.BLOG, fav=True) Item.objects.create(source=src, user=self.user, kind=Source.BLOG, guid_hash='g', title='T', published=timezone.now(), content='x
', content_full=True) self.post() items = self.client.get('/feeds/blogs/?fav=1').json()['items'] self.assertEqual(len(items), 2) self.assertEqual(sorted('episode_id' in i for i in items), [False, True]) def test_blog_list_needs_no_query_per_article(self): for n in range(5): self.post(ep=PodcastEpisode.objects.create(feed=self.feed, guid=f'x{n}', title=str(n), audio_url='https://p.example/x.mp3')) with self.assertNumQueries(3): self.client.get('/feeds/blogs/?fav=1')