diff --git a/CHANGELOG.md b/CHANGELOG.md index cf886858..938f3a84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,13 +2,17 @@ ## Development +## Version 2.0.0 + +- Merged in all 0.8.x changes. + ## Version 1.1.1 - Update video grid styles and add bulbs-video-play-button ## Version 0.11.6 -- Add video recirc widget and global SASS styles +- Add video recirc widget and global SASS styles ## Version 0.11.5 @@ -31,6 +35,16 @@ - TUNIC_REQUEST_TOKEN (ex: "12345") - TUNIC_API_PATH (ex: "/api/v1/") +## Version 0.8.18 + +- Change default sort order of Instant Article feed to last modified time, than published date + +## Version 0.8.17 + +- Add Glance JSON feed for content ingestion: `/feeds/glance.json` +- Instant article improvements +- Targeting + footer improvements + ## Version 0.8.10 - Adds tag-based recirc fallback to `RecircViewSet` `GET` request diff --git a/bulbs/__init__.py b/bulbs/__init__.py index a82b376d..8c0d5d5b 100644 --- a/bulbs/__init__.py +++ b/bulbs/__init__.py @@ -1 +1 @@ -__version__ = "1.1.1" +__version__ = "2.0.0" diff --git a/bulbs/content/managers.py b/bulbs/content/managers.py index 597f6627..718640fc 100644 --- a/bulbs/content/managers.py +++ b/bulbs/content/managers.py @@ -7,7 +7,8 @@ from polymorphic import PolymorphicManager from .filters import ( - Authors, Evergreen, FeatureTypes, InstantArticle, Published, Status, Tags, VideohubChannel + Authors, Evergreen, FeatureTypes, InstantArticle, Published, Status, Tags, + VideohubChannel ) @@ -42,7 +43,7 @@ def instant_articles(self, **kwargs): Instant articles are configured via FeatureType. FeatureType.instant_article = True. """ - eqs = self.search(**kwargs) + eqs = self.search(**kwargs).sort('-last_modified', '-published') return eqs.filter(InstantArticle()) def sponsored(self, **kwargs): diff --git a/bulbs/instant_articles/templates/instant_article/base_instant_article.html b/bulbs/instant_articles/templates/instant_article/base_instant_article.html index b541155c..ba92d403 100644 --- a/bulbs/instant_articles/templates/instant_article/base_instant_article.html +++ b/bulbs/instant_articles/templates/instant_article/base_instant_article.html @@ -1,4 +1,5 @@ {% load betty %} + @@ -49,11 +50,13 @@

- + {% block article_footer %} + + {% endblock article_footer %} - \ No newline at end of file + diff --git a/bulbs/instant_articles/templates/instant_article/base_instant_article_rss.xml b/bulbs/instant_articles/templates/instant_article/base_instant_article_rss.xml index ac79f24b..8e8e62d2 100644 --- a/bulbs/instant_articles/templates/instant_article/base_instant_article_rss.xml +++ b/bulbs/instant_articles/templates/instant_article/base_instant_article_rss.xml @@ -7,11 +7,11 @@ en-us {{ build_date|date:"D, d M Y H:i:s O" }} {% for content in page_obj.object_list %} - {{ content.feature_type }}: {{ content.title|striptags }} + {{ content.title|striptags }} {{ content.feed_url }} {{ content.id }} {{ content.published|date:"D, d M Y H:i:s O" }} - {% if content.authors.all %}{% for author in content.authors.all %}{{ author.get_full_name }}{% if not forloop.last %}, {% endif %}{% endfor%}{% endif %} + {% block authors %}{% if content.authors.all %}{% for author in content.authors.all %}{{ author.get_full_name }}{% if not forloop.last %}, {% endif %}{% endfor%}{% endif %}{% endblock authors %} ', - # str(response.content) - # ) + self.assertEqual(DFP_SITE, targeting.get("dfp_site")) + self.assertEqual(slugify(self.feature_type), targeting.get("dfp_feature")) + self.assertEqual(self.content.id, targeting.get("dfp_contentid")) + self.assertEqual(self.content.__class__.__name__.lower(), targeting.get("dfp_pagetype")) + self.assertEqual(self.content.slug, targeting.get("dfp_slug")) diff --git a/tests/instant_articles/test_ia_feed.py b/tests/instant_articles/test_ia_feed.py index 4a59e314..c4671191 100644 --- a/tests/instant_articles/test_ia_feed.py +++ b/tests/instant_articles/test_ia_feed.py @@ -28,6 +28,26 @@ def test_pagination(self): content_list = resp.context_data['content_list'] self.assertEqual(len(content_list), 100) + def test_sort_order(self): + content1 = TestContentObj.objects.create( + title='TestContentObj 1', + feature_type=self.news_in_brief, + published=timezone.now() - timezone.timedelta(days=1) + ) + content2 = TestContentObj.objects.create( + title='TestContentObj 2', + feature_type=self.news_in_brief, + published=timezone.now() - timezone.timedelta(days=5) + ) + TestContentObj.search_objects.refresh() + endpoint = reverse('instant_articles') + resp = self.client.get(endpoint) + self.assertEqual(resp.status_code, 200) + content_list = resp.context_data['content_list'] + self.assertEqual(len(content_list), 2) + self.assertEqual(content_list[0].id, content2.id) + self.assertEqual(content_list[1].id, content1.id) + def test_project_not_base_template(self): for i in range(100): TestContentObj.objects.create( diff --git a/tests/instant_articles/test_instant_article_analytics.py b/tests/instant_articles/test_instant_article_analytics.py index 88a07ab9..326367a1 100644 --- a/tests/instant_articles/test_instant_article_analytics.py +++ b/tests/instant_articles/test_instant_article_analytics.py @@ -1,5 +1,8 @@ +from django.contrib.auth import get_user_model from django.core.urlresolvers import reverse +from django.template.defaultfilters import slugify from django.test.client import Client +from django.test.utils import override_settings from bulbs.content.models import FeatureType from bulbs.utils.test import make_content, BaseIndexableTestCase @@ -7,6 +10,9 @@ from example.testcontent.models import TestContentObj +DFP_SITE = "www.google.com" + + class AnalyticsViewTests(BaseIndexableTestCase): def setUp(self): @@ -15,10 +21,24 @@ def setUp(self): name="Ey go that way bruh", instant_article=True ) self.content = make_content(TestContentObj, feature_type=self.feature_type) + User = get_user_model() + admin = self.admin = User.objects.create_user("admin", "tech@theonion.com", "secret") + admin.is_staff = True + admin.save() + @override_settings(DFP_SITE=DFP_SITE) def test_analytics(self): self.client = Client() + self.client.login(username="admin", password="secret") url = reverse("instant_article_analytics", kwargs={"pk": self.content.pk}) + response = self.client.get(url) + targeting = response.context_data.get("targeting") + self.assertEqual(response.status_code, 200) self.assertEqual("Instant Articles", response.context_data.get("platform")) + self.assertEqual(DFP_SITE, targeting.get("dfp_site")) + self.assertEqual(slugify(self.feature_type), targeting.get("dfp_feature")) + self.assertEqual(self.content.id, targeting.get("dfp_contentid")) + self.assertEqual(self.content.__class__.__name__.lower(), targeting.get("dfp_pagetype")) + self.assertEqual(self.content.slug, targeting.get("dfp_slug")) diff --git a/tests/instant_articles/test_instant_article_view.py b/tests/instant_articles/test_instant_article_view.py new file mode 100644 index 00000000..db337d3f --- /dev/null +++ b/tests/instant_articles/test_instant_article_view.py @@ -0,0 +1,41 @@ +from django.contrib.auth import get_user_model +from django.core.urlresolvers import reverse +from django.template.defaultfilters import slugify +from django.test.client import Client +from django.test.utils import override_settings + +from bulbs.content.models import FeatureType +from bulbs.utils.test import make_content, BaseIndexableTestCase + +from example.testcontent.models import TestContentObj + + +DFP_SITE = "www.google.com" + + +class InstantArticleAdViewTests(BaseIndexableTestCase): + def setUp(self): + super(InstantArticleAdViewTests, self).setUp() + self.client = Client() + self.feature_type = FeatureType.objects.create(name="AdBoys", instant_article=True) + self.content = make_content(TestContentObj, feature_type=self.feature_type) + self.url = reverse("instant_article", kwargs={"pk": self.content.pk}) + + User = get_user_model() + admin = self.admin = User.objects.create_user("admin", "tech@theonion.com", "secret") + admin.is_staff = True + admin.save() + + @override_settings(DFP_SITE=DFP_SITE) + def test_ad_unit(self): + self.client.login(username="admin", password="secret") + + response = self.client.get(self.url) + targeting = response.context_data.get("targeting") + + self.assertEqual(response.status_code, 200) + self.assertEqual(DFP_SITE, targeting.get("dfp_site")) + self.assertEqual(slugify(self.feature_type), targeting.get("dfp_feature")) + self.assertEqual(self.content.id, targeting.get("dfp_contentid")) + self.assertEqual(self.content.__class__.__name__.lower(), targeting.get("dfp_pagetype")) + self.assertEqual(self.content.slug, targeting.get("dfp_slug"))