def testMulitpleSchedule(self): self.setMockUser() test_feed_url = 'http://example.com/rss' self.set_rss_response(test_feed_url, content=self.buildRSS('test'), status_code=200) resp = self.app.post('/api/feeds', data=dict( feed_url=test_feed_url, include_summary=True, max_stories_per_period=2, schedule_period=5, ), headers=self.authHeaders()) assert 1 == Entry.query(Entry.published == True, Entry.overflow == True).count() self.pollUpdate() self.set_rss_response(test_feed_url, content=self.buildRSS('test2'), status_code=200) self.pollUpdate() # Should not have been rate limited assert 1 == Entry.query(Entry.published == True, Entry.overflow == False).count() self.set_rss_response(test_feed_url, content=self.buildRSS('test3'), status_code=200) self.pollUpdate() # Should not have been rate limited assert 2 == Entry.query(Entry.published == True, Entry.overflow == False).count() self.set_rss_response(test_feed_url, content=self.buildRSS('test4'), status_code=200) self.pollUpdate() # Should have been rate limited assert 2 == Entry.query(Entry.published == True, Entry.overflow == False).count() # We should have burned off the latest entry burned_entries = Entry.query(Entry.published == True, Entry.overflow == True).fetch(2) assert 1 == len(burned_entries) # So, the first entry was burned because it was already in the feed assert burned_entries[0].overflow_reason == OVERFLOW_REASON.BACKLOG
def testPush(self): self.setMockUser() self.set_response('http://pubsubhubbub.appspot.com', content='', status_code=200, method="POST") test_feed_url = 'http://example.com/rss' self.set_rss_response(test_feed_url, content=self.buildRSS('test', push_hub=True), status_code=200) resp = self.app.post('/api/feeds', data=dict( feed_url=test_feed_url, include_summary=True, max_stories_per_period=1, schedule_period=5, ), headers=self.authHeaders()) feed = Feed.query().get() resp = self.app.get('/api/feeds/%s/subscribe' % (feed.key.urlsafe(), ), query_string={ "hub.mode": 'subscribe', "hub.topic": feed.feed_url, "hub.challenge": 'testing', "hub.verify_token": feed.verify_token, }) assert resp.data == 'testing' data = get_file_from_data('/data/df_feed.xml') resp = self.app.post('/api/feeds/%s/subscribe' % (feed.key.urlsafe(), ), data=data, headers={ 'Content-Type': 'application/xml', }) assert 2 == Entry.query().count() assert 1 == Entry.query(Entry.published == True, Entry.overflow == False).count() resp = self.app.post('/api/feeds/%s/subscribe' % (feed.key.urlsafe(), )) assert 2 == Entry.query(Entry.published == True).count()
def testSchedule(self): self.setMockUser() test_feed_url = 'http://example.com/rss' self.set_rss_response(test_feed_url, content=self.buildRSS('test1'), status_code=200) resp = self.app.post('/api/feeds', data=dict( feed_url=test_feed_url, include_summary=True, max_stories_per_period=1, schedule_period=5, ), headers=self.authHeaders()) assert 0 == Entry.query(Entry.published == True, Entry.overflow == False).count() self.set_rss_response(test_feed_url, content=self.buildRSS('test2',), status_code=200) self.pollUpdate() assert 1 == Entry.query(Entry.published == True, Entry.overflow == False).count() self.set_rss_response(test_feed_url, content=self.buildRSS('test3'), status_code=200) self.pollUpdate() # Should have been rate limited assert 1 == Entry.query(Entry.published == True, Entry.overflow == False).count() # Set the entry back in time first_entry = Entry.query(Entry.published == True, Entry.overflow == False).get() first_entry.published_at = first_entry.published_at - timedelta(minutes=10) first_entry.put() self.set_rss_response(test_feed_url, content=self.buildRSS('test4'), status_code=200) self.pollUpdate() # Should not have been rate limited assert 2 == Entry.query(Entry.published == True, Entry.overflow == False).count()
def testPoller(self): self.setMockUser() another_fake_access_token = 'another_banana_stand' self.setMockUser(access_token=another_fake_access_token, username='******', id=2) test_feed_url = 'http://example.com/rss' self.set_rss_response(test_feed_url, content=self.buildRSS('test'), status_code=200) resp = self.app.post('/api/feeds', data=dict( feed_url=test_feed_url, ), headers=self.authHeaders()) test_feed_url = 'http://example.com/rss2' self.set_rss_response(test_feed_url, content=self.buildRSS('test'), status_code=200) resp = self.app.post('/api/feeds', data=dict( feed_url=test_feed_url, ), headers={'Authorization': 'Bearer %s' % (another_fake_access_token, )}) assert 2 == Entry.query().count() test_feed_url = 'http://example.com/rss2' self.set_rss_response(test_feed_url, content=self.buildRSS('test2'), status_code=200) self.pollUpdate(2, n=0) assert 2 == Entry.query().count() self.pollUpdate() assert 3 == Entry.query().count()
def testFeed(self): self.setMockUser() resp = self.app.get('/api/feeds', headers=self.authHeaders()) json_resp = json.loads(resp.data) assert len(json_resp['data']) == 0 self.set_rss_response("http://example.com/rss", content=self.buildRSS('test', items=10), status_code=200) test_feed_url = 'http://example.com/rss' # Should fail validation resp = self.app.post('/api/feeds', data=dict( feed_url=test_feed_url, max_stories_per_period=0, schedule_period=5, ), headers=self.authHeaders()) assert 0 == Feed.query().count() resp = self.app.post('/api/feeds', data=dict( feed_url=test_feed_url, include_summary='true', max_stories_per_period=1, schedule_period=5, ), headers=self.authHeaders()) json_resp = json.loads(resp.data) assert json_resp['data']['feed_url'] == test_feed_url assert 10 == Entry.query(Entry.published == True, Entry.overflow == True).count() feed_id = json_resp['data']['feed_id'] resp = self.app.get('/api/feeds/%s' % feed_id, headers=self.authHeaders()) json_resp = json.loads(resp.data) assert len(json_resp['data']['entries']) == 10 assert json_resp['data']['entries'][0]['guid'] == "http://example.com/buster/test_0" # Shouldn't be able to create two feeds for the same user resp = self.app.post('/api/feeds', data=dict( feed_url=test_feed_url, include_summary='true', max_stories_per_period=1, schedule_period=5, ), headers=self.authHeaders()) json_resp = json.loads(resp.data) assert 1 == Feed.query().count() resp = self.app.get('/api/feeds', headers=self.authHeaders()) json_resp = json.loads(resp.data) assert len(json_resp['data']) == 1 self.set_rss_response("http://example.com/rss", content=self.buildRSS('test2'), status_code=200) feed = Feed.query().get() Entry.update_for_feed(feed) assert 11 == Entry.query().count()
def testLargeOverflow(self): self.setMockUser() test_feed_url = 'http://example.com/rss' self.set_rss_response(test_feed_url, content=self.buildRSS('test', items=6), status_code=200) resp = self.app.post('/api/feeds', data=dict( feed_url=test_feed_url, include_summary=True, max_stories_per_period=2, schedule_period=5, ), headers=self.authHeaders()) assert 0 == Entry.query(Entry.published == True, Entry.overflow == False).count() self.set_rss_response(test_feed_url, content=self.buildRSS('test2', items=6), status_code=200) resp = self.app.get('/api/feeds/all/update/1', headers={'X-Appengine-Cron': 'true'}) assert 2 == Entry.query(Entry.published == True, Entry.overflow == False).count() assert 10 == Entry.query(Entry.published == True, Entry.overflow == True).count()
def testTags(self): self.setMockUser() test_feed_url = 'http://example.com/rss' self.set_rss_response(test_feed_url, content=self.buildRSS('test', items=1), status_code=200) self.app.post('/api/feeds', data=dict( feed_url=test_feed_url, include_summary=True, max_stories_per_period=2, schedule_period=5, ), headers=self.authHeaders()) entry = Entry.query().order(-Entry.added).get() assert [] == entry.tags self.set_rss_response(test_feed_url, content=self.buildRSS('test1', items=1, tags=['example', 'feed']), status_code=200) self.pollUpdate() entry = Entry.query().order(-Entry.added).fetch(2)[0] assert ['example', 'feed'] == entry.tags
def testAuthor(self): self.setMockUser() test_feed_url = 'http://example.com/rss' self.set_rss_response(test_feed_url, content=self.buildRSS('test', items=1), status_code=200) self.app.post('/api/feeds', data=dict( feed_url=test_feed_url, include_summary=True, max_stories_per_period=2, schedule_period=5, ), headers=self.authHeaders()) entry = Entry.query().order(-Entry.added).get() assert None == entry.author self.set_rss_response(test_feed_url, content=self.buildRSS('test1', items=1, author='Alex Kessinger'), status_code=200) self.pollUpdate() entry = Entry.query().order(-Entry.added).get() assert 'Alex Kessinger' == entry.author
def testAuthor(self): self.setMockUser() test_feed_url = 'http://example.com/rss' self.set_rss_response(test_feed_url, content=self.buildRSS('test', items=1), status_code=200) resp = self.app.post('/api/feeds', data=dict( feed_url=test_feed_url, include_summary=True, max_stories_per_period=2, schedule_period=5, ), headers=self.authHeaders()) entry = Entry.query().get() assert None == entry.author self.set_rss_response(test_feed_url, content=self.buildRSS('test1', items=1, author='Alex Kessinger'), status_code=200) resp = self.app.get('/api/feeds/all/update/1', headers={'X-Appengine-Cron': 'true'}) entry = Entry.query().fetch(2)[1] assert 'Alex Kessinger' == entry.author
def testShortUrl(self): self.setMockUser() self.set_rss_response("https://api-ssl.bitly.com/v3/shorten?login=example&apiKey=R_123&longUrl=http%3A%2F%2Fexample.com%2Fbuster%2Ftest1_0%3Futm_medium%3DApp.net%26utm_source%3DPourOver", content=BIT_LY_RESPONSE) test_feed_url = 'http://example.com/rss' self.set_rss_response(test_feed_url, content=self.buildRSS('test', items=1), status_code=200) resp = self.app.post('/api/feeds', data=dict( feed_url=test_feed_url, include_summary=True, max_stories_per_period=2, schedule_period=5, bitly_login='******', bitly_api_key='R_123', ), headers=self.authHeaders()) entry = Entry.query().get() assert [] == entry.tags self.set_rss_response(test_feed_url, content=self.buildRSS('test1', items=1), status_code=200) resp = self.app.get('/api/feeds/all/update/1', headers={'X-Appengine-Cron': 'true'}) entry = Entry.query().fetch(2)[1] assert entry.short_url == 'http://bit.ly/123'
def testSingleItemPublish(self): self.setMockUser() test_feed_url = 'http://example.com/rss' self.set_rss_response(test_feed_url, content=self.buildRSS('test'), status_code=200) resp = self.app.post('/api/feeds', data=dict( feed_url=test_feed_url, include_summary=True, max_stories_per_period=2, schedule_period=5, ), headers=self.authHeaders()) entry = Entry.query().get() feed = Feed.query().get() resp = self.app.post('/api/feeds/%s/entries/%s/publish' % (feed.key.id(), entry.key.id()), headers=self.authHeaders())
def testFeedPreview(self): self.set_rss_response('http://techcrunch.com/feed/', content=self.buildRSS('test'), status_code=200) resp = self.app.get('/api/feed/preview?feed_url=http://techcrunch.com/feed/', headers=self.authHeaders()) assert 1 == len(json.loads(resp.data)['data']) self.set_rss_response('http://techcrunch.com/feed/2', content=self.buildRSS('test'), status_code=500) resp = self.app.get('/api/feed/preview?feed_url=http://techcrunch.com/feed/2', headers=self.authHeaders()) assert json.loads(resp.data)['message'] test_feed_url = 'http://example.com/rss' self.set_rss_response(test_feed_url, content=self.buildRSS('test'), status_code=200) resp = self.app.post('/api/feeds', data=dict( feed_url=test_feed_url, include_summary=True, max_stories_per_period=2, schedule_period=5, ), headers=self.authHeaders()) assert 1 == Entry.query(Entry.published == True, Entry.overflow == True).count() feed = Feed.query().get() resp = self.app.get('/api/feeds/%s/preview' % (feed.key.id(), ), headers=self.authHeaders()) assert 'data' in json.loads(resp.data)
def testDbRaceCondition(self): self.setMockUser() test_feed_url = 'http://example.com/rss' self.set_rss_response(test_feed_url, content=self.buildRSS('test', items=1), status_code=200) self.app.post('/api/feeds', data=dict( feed_url=test_feed_url, include_summary=True, max_stories_per_period=2, schedule_period=5, ), headers=self.authHeaders()) feed = Feed.query().get() key = ndb.Key(Entry, '1', parent=feed.key) entry = Entry(key=key, guid='1') entry.put() entry_2 = Entry(key=key, guid='2') entry_2.put() assert Entry.query().count() == 2