def test_conform_target_subscribers(self): doc = {'headline': 'test'} subscriber = {'_id': 1} self.assertTupleEqual( (True, False), EnqueueService().conforms_subscriber_targets(subscriber, doc)) doc = {'headline': 'test', 'target_subscribers': []} self.assertTupleEqual( (True, False), EnqueueService().conforms_subscriber_targets(subscriber, doc)) doc = {'headline': 'test', 'target_subscribers': [{'_id': 2}]} self.assertTupleEqual( (False, False), EnqueueService().conforms_subscriber_targets(subscriber, doc)) doc = {'headline': 'test', 'target_subscribers': [{'_id': 1}]} self.assertTupleEqual( (True, True), EnqueueService().conforms_subscriber_targets(subscriber, doc)) doc = { 'headline': 'test', 'target_subscribers': [{ '_id': 2 }], 'target_regions': [{ 'name': 'Victoria' }] } self.assertTupleEqual( (True, False), EnqueueService().conforms_subscriber_targets(subscriber, doc))
def setUp(self): super().setUp() self.product_ids = self.app.data.insert( "products", [ {"name": "all"}, ], ) self.subscriber_ids = self.app.data.insert( "subscribers", [ {"name": "digi", "subscriber_type": "digital", "is_targetable": True, "products": self.product_ids}, ], ) self.desk_ids = self.app.data.insert( "desks", [ {"name": "sports"}, ], ) self.service = EnqueueService()
class NoTakesEnqueueTestCase(TestCase): def setUp(self): super().setUp() self.product_ids = self.app.data.insert('products', [ {'name': 'all'}, ]) self.subscriber_ids = self.app.data.insert('subscribers', [ {'name': 'digi', 'subscriber_type': 'digital', 'is_targetable': True, 'products': self.product_ids}, ]) self.desk_ids = self.app.data.insert('desks', [ {'name': 'sports'}, ]) self.service = EnqueueService() def test_resend_no_takes(self): doc = {'_id': 'test'} subscribers = [s for s in self.app.data.find_all('subscribers')] subscriber_codes = self.service._get_subscriber_codes(subscribers) with patch.object(self.service, '_resend_to_subscribers') as resend: with patch.object(self.service, 'publish_content_api') as content_api: with patch.dict('apps.publish.enqueue.enqueue_service.app.config', {'NO_TAKES': True}): self.service.resend(doc, subscribers) resend.assert_called_with(doc, subscribers, subscriber_codes, {}) content_api.assert_called_with(doc, [])
def test_previously_sent_item_association_for_removed_associations(self): service = EnqueueService() subscribers, subscriber_codes, associated_items = service._get_subscribers_for_previously_sent_items( {"item_id": "3"}) self.assertEqual(len(associated_items.keys()), 1) self.assertIn("sub3", list(associated_items.keys())) self.assertIn("786", associated_items["sub3"])
def test_products(self, article): req = ParsedRequest() results = [] products = list( get_resource_service('products').get(req=req, lookup=None)) for product in products: result = {} result['product_id'] = product['_id'] result['matched'] = True reason = '' if not EnqueueService().conforms_product_targets(product, article): # Here it fails to match due to geo restriction # story has target_region and product has geo restriction result['matched'] = False if BasePublishService().is_targeted(article, 'target_regions'): reason = 'Story has target_region' if product.get('geo_restrictions'): reason = '{} {}'.format(reason, 'Product has target_region') if not EnqueueService().conforms_content_filter(product, article): # Here it fails to match due to content filter content_filter = product.get('content_filter') filter = get_resource_service('content_filters').find_one( req=None, _id=content_filter['filter_id']) result['matched'] = False reason = 'Story does not match the filter: {}'.format( filter.get('name')) result['reason'] = reason results.append(result) return results
def setUp(self): super().setUp() self.product_ids = self.app.data.insert('products', [ { 'name': 'all' }, ]) self.subscriber_ids = self.app.data.insert('subscribers', [ { 'name': 'digi', 'subscriber_type': 'digital', 'is_targetable': True, 'products': self.product_ids }, ]) self.desk_ids = self.app.data.insert('desks', [ { 'name': 'sports' }, ]) self.service = EnqueueService()
def test_previously_sent_item_association_for_removed_associations(self): service = EnqueueService() subscribers, subscriber_codes, associated_items = \ service._get_subscribers_for_previously_sent_items({'item_id': '3'}) self.assertEqual(len(associated_items.keys()), 1) self.assertIn('sub3', list(associated_items.keys())) self.assertIn('786', associated_items['sub3'])
def test_previously_sent_item_association_for_multiple_subscribers(self): service = EnqueueService() subscribers, subscriber_codes, associated_items = service._get_subscribers_for_previously_sent_items( {"item_id": "2"}) self.assertEqual(len(associated_items.keys()), 2) self.assertIn("sub2", associated_items) self.assertIn("sub4", associated_items) self.assertIn("123", associated_items["sub2"]) self.assertIn("456", associated_items["sub2"]) self.assertIn("123", associated_items["sub4"]) self.assertIn("456", associated_items["sub4"])
def test_can_publish_article(self): product = self.products[0] self._add_content_filters(product, is_global=False) can_it = EnqueueService().conforms_content_filter(product, self.articles[8]) self.assertFalse(can_it) product['content_filter']['filter_type'] = 'permitting' can_it = EnqueueService().conforms_content_filter(product, self.articles[8]) self.assertTrue(can_it) product.pop('content_filter')
def test_previously_sent_item_association_for_multiple_subscribers(self): service = EnqueueService() subscribers, subscriber_codes, associated_items = \ service._get_subscribers_for_previously_sent_items({'item_id': '2'}) self.assertEqual(len(associated_items.keys()), 2) self.assertIn('sub2', associated_items) self.assertIn('sub4', associated_items) self.assertIn('123', associated_items['sub2']) self.assertIn('456', associated_items['sub2']) self.assertIn('123', associated_items['sub4']) self.assertIn('456', associated_items['sub4'])
def create(self, docs, **kwargs): doc = docs[0] if len(docs) > 0 else {} article_id = request.view_args['original_id'] article_version = doc.get('version') article = self._validate_article(article_id, article_version) subscribers = self._validate_subscribers(doc.get('subscribers')) EnqueueService().resend(article, subscribers) return [article_id]
def test_get_changed_items_no_item_found(self): # dummy publishing so that elastic mappings are created. doc = self.articles[3].copy() get_resource_service(ARCHIVE_PUBLISH).patch( id=doc['_id'], updates={ITEM_STATE: CONTENT_STATE.PUBLISHED}) removed_items, added_items = EnqueueService()._get_changed_items( {}, {'item_id': 'test'}) self.assertEqual(len(removed_items), 0) self.assertEqual(len(added_items), 0)
def test_can_publish_article_with_global_filters(self): subscriber = self.subscribers[0] product = self.products[0] self._add_content_filters(product, is_global=True) service = get_resource_service('content_filters') req = ParsedRequest() req.args = {'is_global': True} global_filters = service.get(req=req, lookup=None) can_it = EnqueueService().conforms_global_filter(subscriber, global_filters, self.articles[8]) self.assertFalse(can_it) subscriber['global_filters'] = {'1': False} can_it = EnqueueService().conforms_global_filter(subscriber, global_filters, self.articles[8]) self.assertTrue(can_it) product.pop('content_filter')
def test_can_publish_article_with_global_filters(self): subscriber = self.subscribers[0] product = self.products[0] self._add_content_filters(product, is_global=True) service = get_resource_service('content_filters') req = ParsedRequest() req.args = {'is_global': True} global_filters = list(service.get(req=req, lookup=None)) enqueue_service = EnqueueService() enqueue_service.conforms_global_filter(global_filters, self.articles[4]) can_it = enqueue_service.conforms_subscriber_global_filter(subscriber, global_filters) self.assertFalse(can_it) subscriber['global_filters'] = {'1': False} can_it = enqueue_service.conforms_subscriber_global_filter(subscriber, global_filters) self.assertTrue(can_it) product.pop('content_filter')
def create(self, docs, **kwargs): doc = docs[0] if len(docs) > 0 else {} article_id = request.view_args['original_id'] article_version = doc.get('version') article = self._validate_article(article_id, article_version) subscribers = self._validate_subscribers(doc.get('subscribers'), article) EnqueueService().resend(article, subscribers) app.on_archive_item_updated({'subscribers': doc.get('subscribers')}, article, ITEM_RESEND) return [article_id]
def test_queue_transmission_wrong_article_type_fails(self): self._is_publish_queue_empty() doc = copy(self.articles[0]) doc['item_id'] = doc['_id'] doc[ITEM_TYPE] = CONTENT_TYPE.PICTURE subscribers, subscribers_yet_to_receive, subscriber_codes = \ EnqueuePublishedService().get_subscribers(doc, SUBSCRIBER_TYPES.DIGITAL) no_formatters, queued = EnqueueService().queue_transmission(doc, subscribers, subscriber_codes) queue_items = self.app.data.find(PUBLISH_QUEUE, None, None) self.assertEqual(1, queue_items.count()) self.assertEqual(0, len(no_formatters)) self.assertTrue(queued) subscribers, subscribers_yet_to_receive, subscriber_codes = \ EnqueuePublishedService().get_subscribers(doc, SUBSCRIBER_TYPES.WIRE) no_formatters, queued = EnqueueService().queue_transmission(doc, subscribers) queue_items = self.app.data.find(PUBLISH_QUEUE, None, None) self.assertEqual(2, queue_items.count()) self.assertEqual(0, len(no_formatters)) self.assertTrue(queued)
def publish(self, item, subscribers=None): """Publish an item to content api. This must be enabled via ``PUBLISH_TO_CONTENT_API`` setting. :param item: item to publish """ if subscribers is None: subscribers = [] if not self._filter_item(item): item = EnqueueService.filter_document(item) item = remove_metadata_for_publish(item) doc = self.formatter._transform_to_ninjs(item, self.subscriber) now = utcnow() doc.setdefault("firstcreated", now) doc.setdefault("versioncreated", now) doc.setdefault(config.VERSION, item.get(config.VERSION, 1)) for _, assoc in doc.get(ASSOCIATIONS, {}).items(): if assoc: assoc.setdefault("subscribers", [ str(subscriber[config.ID_FIELD]) for subscriber in subscribers ]) doc["subscribers"] = [str(sub["_id"]) for sub in subscribers] doc["original_id"] = doc["guid"] if "evolvedfrom" in doc: parent_item = self.find_one(req=None, _id=doc["evolvedfrom"]) if parent_item: if parent_item.get("original_id"): doc["original_id"] = parent_item["original_id"] doc["ancestors"] = copy(parent_item.get("ancestors", [])) doc["ancestors"].append(doc["evolvedfrom"]) doc["bookmarks"] = parent_item.get("bookmarks", []) else: logger.warning( "Failed to find evolvedfrom item '{}' for '{}'".format( doc["evolvedfrom"], doc["guid"])) self._assign_associations(item, doc) logger.info("publishing %s to %s" % (doc["guid"], subscribers)) _id = self._create_doc(doc) if "evolvedfrom" in doc and parent_item: self.system_update(parent_item["_id"], {"nextversion": _id}, parent_item) return _id else: return None
class NoTakesEnqueueTestCase(TestCase): def setUp(self): super().setUp() self.product_ids = self.app.data.insert( "products", [ {"name": "all"}, ], ) self.subscriber_ids = self.app.data.insert( "subscribers", [ {"name": "digi", "subscriber_type": "digital", "is_targetable": True, "products": self.product_ids}, ], ) self.desk_ids = self.app.data.insert( "desks", [ {"name": "sports"}, ], ) self.service = EnqueueService() def test_resend_no_takes(self): doc = {"_id": "test"} subscribers = [s for s in self.app.data.find_all("subscribers")] subscriber_codes = self.service._get_subscriber_codes(subscribers) with patch.object(self.service, "_resend_to_subscribers") as resend: with patch.object(self.service, "publish_content_api") as content_api: self.service.resend(doc, subscribers) resend.assert_called_with(doc, subscribers, subscriber_codes, {}) content_api.assert_called_with(doc, [])
def test_queue_transmission_for_digital_channels(self): self._is_publish_queue_empty() doc = copy(self.articles[1]) doc['item_id'] = doc['_id'] subscribers, subscribers_yet_to_receive, subscriber_codes = \ EnqueuePublishedService().get_subscribers(doc, SUBSCRIBER_TYPES.DIGITAL) EnqueueService().queue_transmission(doc, subscribers, subscriber_codes) queue_items = self.app.data.find(PUBLISH_QUEUE, None, None) self.assertEqual(1, queue_items.count()) expected_subscribers = ['5'] for item in queue_items: self.assertIn(item["subscriber_id"], expected_subscribers, 'item {}'.format(item))
def test_queue_transmission_for_wire_channels_with_codes(self): self._is_publish_queue_empty() doc = copy(self.articles[1]) doc['item_id'] = doc['_id'] subscribers, subscribers_yet_to_receive, subscriber_codes = \ EnqueuePublishedService().get_subscribers(doc, SUBSCRIBER_TYPES.WIRE) EnqueueService().queue_transmission(doc, subscribers, subscriber_codes) queue_items = self.app.data.find(PUBLISH_QUEUE, None, None) self.assertEqual(5, queue_items.count()) expected_subscribers = ['1', '2', '4', '5'] for item in queue_items: self.assertIn(item['subscriber_id'], expected_subscribers, 'item {}'.format(item)) if item['subscriber_id'] == '5': self.assertIn('def', item['codes']) self.assertIn('abc', item['codes'])
def test_conform_target_regions(self): doc = {'headline': 'test'} product = {'geo_restrictions': 'QLD'} self.assertFalse(EnqueueService().conforms_product_targets( product, doc)) doc = {'headline': 'test', 'target_regions': []} self.assertFalse(EnqueueService().conforms_product_targets( product, doc)) doc = { 'headline': 'test', 'target_regions': [{ 'qcode': 'VIC', 'name': 'Victoria', 'allow': True }] } self.assertFalse(EnqueueService().conforms_product_targets( product, doc)) doc = { 'headline': 'test', 'target_regions': [{ 'qcode': 'VIC', 'name': 'Victoria', 'allow': False }] } self.assertTrue(EnqueueService().conforms_product_targets( product, doc)) doc = { 'headline': 'test', 'target_regions': [{ 'qcode': 'QLD', 'name': 'Queensland', 'allow': True }] } self.assertTrue(EnqueueService().conforms_product_targets( product, doc)) doc = { 'headline': 'test', 'target_regions': [{ 'qcode': 'QLD', 'name': 'Queensland', 'allow': False }] } self.assertFalse(EnqueueService().conforms_product_targets( product, doc))
def publish(self, item, subscribers=[]): """Publish an item to content api. This must be enabled via ``PUBLISH_TO_CONTENT_API`` setting. :param item: item to publish """ if not self._filter_item(item): item = EnqueueService.filter_document(item) doc = self.formatter._transform_to_ninjs(item, self.subscriber) now = utcnow() doc.setdefault('firstcreated', now) doc.setdefault('versioncreated', now) doc.setdefault(config.VERSION, item.get(config.VERSION, 1)) for _, assoc in doc.get(ASSOCIATIONS, {}).items(): if assoc: assoc.setdefault('subscribers', [ str(subscriber[config.ID_FIELD]) for subscriber in subscribers ]) doc['subscribers'] = [str(sub['_id']) for sub in subscribers] if 'evolvedfrom' in doc: parent_item = self.find_one(req=None, _id=doc['evolvedfrom']) if parent_item: doc['ancestors'] = copy(parent_item.get('ancestors', [])) doc['ancestors'].append(doc['evolvedfrom']) doc['bookmarks'] = parent_item.get('bookmarks', []) else: logger.warning( "Failed to find evolvedfrom item '{}' for '{}'".format( doc['evolvedfrom'], doc['guid'])) self._assign_associations(item, doc) logger.info('publishing %s to %s' % (doc['guid'], subscribers)) _id = self._create_doc(doc) if 'evolvedfrom' in doc and parent_item: self.system_update(parent_item['_id'], {'nextversion': _id}, parent_item) return _id else: return None
def test_content_api_package_publishing(self, content_api_publish): service = EnqueueService() service.enqueue_item(self.content_api_package) # Mock.assert_called_once is only available in Python 3.6 # so we emulate it by counting the number of calls assert content_api_publish.call_count == 1
def test_previously_sent_item_association_for_no_associations(self): service = EnqueueService() subscribers, subscriber_codes, associated_items = service._get_subscribers_for_previously_sent_items( {"item_id": "5"}) self.assertEqual(len(associated_items.keys()), 0)