def test_entry_unchanged(monkeypatch, feed_template, feed_context): feed = FeedFactory.create(enabled=True) params = { k: v for k, v in feed_context.items() if not k.endswith("date_str") } existing = EntryFactory.create(rss_feed=feed, **params) modified = existing.modified_at def mock_return(feed): return feed_template % feed_context monkeypatch.setattr(feeds, "get_source", mock_return) feeds.load_feed(feed) entries = Entry.objects.filter(modified_at__gt=existing.modified_at) existing.refresh_from_db() events = Event.objects.entry_updates() # No entries were updated assert list(entries) == [] # No events were generated assert events.exists() is False # Existing Article is unchanged assert existing.modified_at == modified
def test_entry_added(monkeypatch, feed_template, feed_context): # feedparser can parse a file, url or string so we can use the get_url() # function in the feeds module to inject a string instead of the Blog's # url and get feedparser to parse it and return the entries. def mock_return(feed): return feed_template % feed_context monkeypatch.setattr(feeds, "get_source", mock_return) feed = FeedFactory.create(enabled=True) feeds.load_feed(feed) entries = Entry.objects.all() # Results contain added Entry assert len(entries) == 1 # Verify the rss attributes are set to the values from the feed # Ensure microseconds on the date the entry was published are set # to zero, rather than the value when the entry is saved in case # the date is used to see if an entry has changed when the feed # is next loaded. entry = entries[0] assert entry.title == feed_context["title"] assert entry.author == feed_context["author"] assert entry.url == feed_context["url"] assert entry.date == feed_context["date"] assert entry.date.microsecond == 0 assert entry.summary == feed_context["summary"] assert entry.identifier == feed_context["identifier"] assert entry.tags == feed_context["tags"] # Verify the Article attributes are initialised from the entry with # the following exceptions: # # 1. The article title is post-processed to remove trailing periods # and all uppercase titles are corrected. # # 2. An Author object is created using the entry author. article = Article.objects.get(entry=entry) assert article.title is not None assert article.authors.first().name == entry.author assert article.url == entry.url assert article.date == entry.date assert article.summary == entry.summary assert article.entry == entry assert article.source == feed.source assert article.publish == feed.source.auto_publish # Verify the article and source are logged in an Event recording # that the Article was added. event = Event.objects.article_adds().get() assert event.data["article"]["pk"] == article.pk assert event.data["source"]["pk"] == article.source.pk
def test_blank_link(monkeypatch, feed_template, feed_context): """Feed entries with an empty link field are skipped""" def mock_return(feed): feed_context["url"] = "" return feed_template % feed_context monkeypatch.setattr(feeds, "get_source", mock_return) feeds.load_feed(FeedFactory.create(enabled=True)) assert Entry.objects.exists() is False
def test_missing_title(monkeypatch, feed_template, feed_context): """Feed entries with no title field are skipped""" feed_template = feed_template.replace("<title>%(title)s</title>", "") def mock_return(feed): return feed_template % feed_context monkeypatch.setattr(feeds, "get_source", mock_return) feeds.load_feed(FeedFactory.create(enabled=True)) assert Entry.objects.exists() is False
def test_missing_identifier(monkeypatch, feed_template, feed_context): """Feed entries with no identifier are loaded using the url as an identifier""" feed_template = feed_template.replace("<id>%(identifier)s</id>", "") def mock_return(feed): return feed_template % feed_context monkeypatch.setattr(feeds, "get_source", mock_return) feeds.load_feed(FeedFactory.create(enabled=True)) assert Entry.objects.exists() is True
def test_blank_tags(monkeypatch, feed_template, feed_context): """Feed entries with an empty tag field are loaded""" def mock_return(feed): feed_context["tags"] = "" return feed_template % feed_context monkeypatch.setattr(feeds, "get_source", mock_return) feeds.load_feed(FeedFactory.create(enabled=True)) assert Entry.objects.get().tags == ""
def test_missing_tags(monkeypatch, feed_template, feed_context): """Feed entries with no tag field are loaded""" feed_template = feed_template.replace( '<category scheme="%(url)s" term="%(tags)s" />', "" ) def mock_return(feed): return feed_template % feed_context monkeypatch.setattr(feeds, "get_source", mock_return) feeds.load_feed(FeedFactory.create(enabled=True)) assert Entry.objects.get().tags == ""
def test_missing_summary(monkeypatch, feed_template, feed_context): """Feed entries with no summary field are loaded""" feed_template = feed_template.replace( '<summary type="text">%(summary)s</summary>', "" ) def mock_return(feed): return feed_template % feed_context monkeypatch.setattr(feeds, "get_source", mock_return) feeds.load_feed(FeedFactory.create(enabled=True)) assert Entry.objects.get().summary == ""
def test_missing_author(monkeypatch, feed_template, feed_context): """Feed entries with no author field are loaded""" feed_template = feed_template.replace( "<author><name>%(author)s</name></author>", "" ) def mock_return(feed): return feed_template % feed_context monkeypatch.setattr(feeds, "get_source", mock_return) feeds.load_feed(FeedFactory.create(enabled=True)) assert Entry.objects.get().author == ""
def test_entry_updated(monkeypatch, feed_template, feed_context): feed = FeedFactory.create(enabled=True, source__auto_publish=True) params = { k: v for k, v in feed_context.items() if not k.endswith("date_str") } existing = EntryFactory.create(rss_feed=feed, **params) feed_context["title"] = "Updated title" updated_title = feed_context["title"] feed.source.auto_publish = False feed.source.save() def mock_return(feed): return feed_template % feed_context monkeypatch.setattr(feeds, "get_source", mock_return) feeds.load_feed(feed) entries = Entry.objects.filter(modified_at__gt=existing.modified_at) # Results contains updated Entry assert len(entries) == 1 # The title of the entry was updated. All other attributes # remain unchanged. entry = entries[0] assert entry.modified_at > existing.modified_at assert entry.title == updated_title assert entry.author == feed_context["author"] assert entry.url == feed_context["url"] assert entry.date == feed_context["date"] assert entry.date.microsecond == 0 assert entry.summary == feed_context["summary"] assert entry.identifier == feed_context["identifier"] assert entry.tags == feed_context["tags"] # The Article created when the Entry was added was not updated. # Changing the default value for the auto_publish flag on the Source # should not affect whether existing Articles are published. article = entry.article assert article.title == "Article title" assert article.authors.first().name == entry.author assert article.url == existing.url assert article.date == existing.date assert article.summary == existing.summary assert article.entry == existing assert article.source == existing.rss_feed.source assert article.publish is True
def load_feed(modeladmin, request, queryset): # noqa for feed in queryset: try: # force the feed to be loaded by resetting the fields # used to send the Last-Modified or ETag headers. feed.loaded_at = None feed.etag = "" result = feeds.load_feed(feed) except DataError: logger.exception("Could not load feed", feed=feed.name) result = False if result: msg = _('The feed "%s" was loaded successfully.' % feed.name) messages.info(request, msg) else: msg = _('There was an error loading the feed "%s"' % feed.name) messages.error(request, msg)