def test_opening_dialog_from_folder_view_points_to_content(self): # Regression VIV-452 from zeit.cms.testcontenttype.testcontenttype import ExampleContentType from zeit.cms.workflow.interfaces import IPublish, IPublishInfo zope.component.hooks.setSite(self.getRootFolder()) self.repository['other'] = ExampleContentType() self.prepare_content('http://xml.zeit.de/other') self.prepare_content('http://xml.zeit.de/testcontent') transaction.commit() IPublish(self.repository['other']).publish(background=False) IPublish(self.repository['testcontent']).publish(background=False) transaction.commit() self.open('/repository') s = self.selenium s.click('xpath=//*[contains(text(), "testcontent")]') s.waitForElementPresent('css=#bottomcontent a[title=Retract]') s.click('css=#bottomcontent a[title="Additional actions"]') s.click('css=#bottomcontent a[title=Retract]') s.waitForElementPresent('css=ol#worklist') s.waitForElementPresent('css=li.busy[action=start_job]') s.waitForElementNotPresent('css=li.busy[action=start_job]') s.waitForPageToLoad() self.assertFalse( IPublishInfo(self.repository['testcontent']).published) self.assertTrue(IPublishInfo(self.repository['other']).published)
def test_error_in_one_item_continues_with_other_items(self): c1 = zeit.cms.interfaces.ICMSContent( 'http://xml.zeit.de/online/2007/01/Somalia') c2 = zeit.cms.interfaces.ICMSContent( 'http://xml.zeit.de/online/2007/01/eta-zapatero') IPublishInfo(c1).urgent = True IPublishInfo(c2).urgent = True calls = [] def after_publish(context, event): calls.append(context.uniqueId) if context.uniqueId == c1.uniqueId: raise RuntimeError('provoked') self.zca.patch_handler(after_publish, (zeit.cms.interfaces.ICMSContent, zeit.cms.workflow.interfaces.IPublishedEvent)) with self.assertRaises(RuntimeError): IPublish(self.repository).publish_multiple([c1, c2], async=False) # PublishedEvent still happens for c2, even though c1 raised self.assertIn(c2.uniqueId, calls) # Error is logged log = zeit.objectlog.interfaces.ILog(c1) self.assertEqual([ u'${name}: ${new_value}', u'Collective Publication', u'Error during publish/retract: ${exc}: ${message}' ], [x.message for x in log.get_log()])
def test_publishinfo_is_reset_for_copied_objects(self): content = self.repository['testcontent'] IPublishInfo(content).published = True copier = zope.copypastemove.interfaces.IObjectCopier(content) new_name = copier.copyTo(self.repository) copied = self.repository[new_name] self.assertEqual(False, IPublishInfo(copied).published)
def test_updates_configured_content_and_publishes(self): self.repository['topics'] = zeit.content.rawxml.rawxml.RawXML() text = zeit.content.text.text.Text() text.text = '' self.repository['redirects'] = text config = zope.app.appsetup.product.getProductConfiguration( 'zeit.retresco') config['topiclist'] = 'http://xml.zeit.de/topics' config['topic-redirect-id'] = 'http://xml.zeit.de/redirects' with mock.patch( 'zeit.retresco.connection.TMS.get_all_topicpages', new=lambda x: iter([{ 'id': 'berlin', 'title': 'Berlin', 'topic_type': 'location', 'redirect': '/thema/hamburg'}])): zeit.retresco.connection._update_topiclist() topics = self.repository['topics'] self.assertEqual(True, IPublishInfo(topics).published) redirects = self.repository['redirects'] self.assertEqual(True, IPublishInfo(redirects).published) self.assertIn('hamburg', redirects.text)
def test_last_published_by_takes_last_entry_from_objectlog(self): content = self.repository['testcontent'] info = IPublishInfo(content) self.assertEqual(None, info.last_published_by) info.urgent = True IPublish(content).publish(background=False) self.assertEqual('zope.user', info.last_published_by)
def test_synchronous_multi_publishing_works_with_unique_ids(self): article = ICMSContent('http://xml.zeit.de/online/2007/01/Somalia') info = IPublishInfo(article) info.urgent = True IPublish(article).publish_multiple([article.uniqueId], background=False) self.assertTrue(info.published)
def test_start_job_retracts_urls(self): self.repository['foo'] = ExampleContentType() self.repository['bar'] = ExampleContentType() IPublishInfo(self.repository['bar']).published = True IPublishInfo(self.repository['foo']).published = True job = zeit.cms.retractlog.retractlog.Job() job.urls = ['http://xml.zeit.de/foo', 'http://xml.zeit.de/bar'] job.start() self.assertFalse(IPublishInfo(self.repository['foo']).published) self.assertFalse(IPublishInfo(self.repository['bar']).published)
def test_object_already_checked_out_should_raise(self): article = ICMSContent('http://xml.zeit.de/online/2007/01/Somalia') IPublishInfo(article).urgent = True zeit.cms.checkout.interfaces.ICheckoutManager(article).checkout() zope.security.management.endInteraction() with zeit.cms.testing.interaction('zope.producer'): with self.assertRaises(Exception) as info: IPublish(article).publish(async=False) self.assertIn('LockingError', str(info.exception)) self.assertEqual(False, IPublishInfo(article).published)
def test_determines_priority_via_adapter(self): content = self.repository['testcontent'] info = IPublishInfo(content) info.urgent = True self.assertFalse(info.published) with mock.patch( 'zeit.cms.workflow.interfaces.IPublishPriority') as priority,\ mock.patch.object(zeit.workflow.publish.PUBLISH_TASK, 'apply_async') as apply_async: priority.return_value = zeit.cms.workflow.interfaces.PRIORITY_LOW IPublish(content).publish() apply_async.assert_called_with(([u'http://xml.zeit.de/testcontent'], ), queuename='publish_lowprio')
def test_delete_button_is_not_displayed_for_folder_with_subfolder(self): folder = self.repository['online'] subfolder = folder['2005'] self.assertFalse(IPublishInfo(folder).published) self.assertFalse(IPublishInfo(subfolder).published) browser = testing.Browser(self.layer['wsgi_app']) browser.login('producer', 'producerpw') browser.open('http://*****:*****@@delete.html') url = link.url.split("'")[1] # embedded in lightbox javascript browser.open(url) with self.assertRaises(LookupError): browser.getControl('Delete') # 'Delete' button is missing
def test_publish_button_publishes_volume_content(self): self.elastic.search.return_value = zeit.cms.interfaces.Result([{ 'url': '/testcontent' }]) with mock.patch('zeit.workflow.publish.PublishTask' '.call_publish_script') as script: self.publish_content() script.assert_called_with( ['work/testcontent', 'work/2015/01/ausgabe']) self.assertTrue(IPublishInfo(self.repository['testcontent']).published) self.assertTrue( IPublishInfo(self.repository['2015']['01']['ausgabe']).published)
def test_publish_and_retract_in_same_process(self): article = ICMSContent('http://xml.zeit.de/online/2007/01/Somalia') info = IPublishInfo(article) info.urgent = True publish = IPublish(article) self.assertFalse(info.published) publish.publish(async=False) self.assertTrue(info.published) publish.retract(async=False) self.assertFalse(info.published) logs = reversed(zeit.objectlog.interfaces.ILog(article).logs) self.assertEqual(['${name}: ${new_value}', 'Published', 'Retracted'], [x.message for x in logs])
def test_delete_button_is_not_displayed_for_folder_with_published_objects( self): folder = self.repository['testing'] folder['foo'] = content = ExampleContentType() self.assertFalse(IPublishInfo(folder).published) IPublishInfo(content).set_can_publish(CAN_PUBLISH_SUCCESS) IPublish(content).publish() browser = testing.Browser(self.layer['wsgi_app']) browser.login('producer', 'producerpw') browser.open('http://*****:*****@@delete.html') url = link.url.split("'")[1] # embedded in lightbox javascript browser.open(url) with self.assertRaises(LookupError): browser.getControl('Delete') # 'Delete' button is missing
def create_article_with_references(self): from zeit.content.article.edit.body import EditableBody from zeit.content.article.article import Article from zeit.content.article.interfaces import IArticle from zeit.content.portraitbox.portraitbox import Portraitbox from zeit.content.infobox.infobox import Infobox import zeit.cms.browser.form article = Article() zeit.cms.content.field.apply_default_values(article, IArticle) article.year = 2017 article.title = u'title' article.ressort = u'Deutschland' portraitbox = Portraitbox() self.repository['portraitbox'] = portraitbox body = EditableBody(article, article.xml.body) portraitbox_reference = body.create_item('portraitbox', 1) portraitbox_reference._validate = mock.Mock() portraitbox_reference.references = portraitbox infobox = Infobox() self.repository['infobox'] = infobox infobox_reference = body.create_item('infobox', 2) infobox_reference._validate = mock.Mock() infobox_reference.references = infobox self.repository['image'] = zeit.cms.interfaces.ICMSContent( 'http://xml.zeit.de/2006/DSC00109_2.JPG') image_reference = body.create_item('image', 3) image_reference.references = image_reference.references.create( self.repository['image']) image_reference._validate = mock.Mock() self.repository['article_with_ref'] = article IPublishInfo(article).urgent = True return self.repository['article_with_ref']
def setup_dates_so_content_is_publishable(self): DAY1 = datetime(2010, 1, 1, tzinfo=pytz.UTC) DAY2 = datetime(2010, 2, 1, tzinfo=pytz.UTC) DAY3 = datetime(2010, 3, 1, tzinfo=pytz.UTC) # XXX it would be nicer to patch this just for the items in question, # but we lack the mechanics to easily substitute adapter instances sem = self.patches.add('zeit.cms.content.interfaces.ISemanticChange') sem().last_semantic_change = DAY1 sem().has_semantic_change = False for item in self.related: info = IPublishInfo(item) info.published = True info.date_last_published = DAY2 dc = self.patches.add('zope.dublincore.interfaces.IDCTimes') dc().modified = DAY3
def test_publish_sends_push_messages(self): # This tests the integration with zeit.push, but not the actual push # methods themselves. self.create_breakingnews() self.fill_in_required_values() self.browser.getControl('Publish and push').click() self.browser.open('@@publish') article = ICMSContent('http://xml.zeit.de/online/2007/01/foo') self.assertEqual(True, IPublishInfo(article).published) for service in ['homepage', 'urbanairship', 'twitter', 'facebook']: notifier = zope.component.getUtility( zeit.push.interfaces.IPushNotifier, name=service) self.assertEqual(1, len(notifier.calls)) self.assertEqual(article.title, notifier.calls[0][0]) urbanairship = zope.component.getUtility( zeit.push.interfaces.IPushNotifier, name='urbanairship') self.assertEqual( 'eilmeldung.json', urbanairship.calls[0][2]['message'].config['payload_template']) facebook = zope.component.getUtility( zeit.push.interfaces.IPushNotifier, name='facebook') self.assertEqual( zeit.push.facebook.facebookAccountSource(None).MAIN_ACCOUNT, facebook.calls[0][2]['account'])
def test_delete_menu_item_is_not_displayed_for_published_objects(self): content = self.repository['testcontent'] IPublishInfo(content).set_can_publish(CAN_PUBLISH_SUCCESS) IPublish(content).publish() self.browser.open( 'http://*****:*****@@delete.html')
def publish(obj): if obj is None: log.info('Got None to publish') return if not IPublishInfo(obj).published: log.info('Publishing %s' % obj) IPublish(obj).publish(background=False) else: log.info('%s already published' % obj)
def test_error_during_publish_is_written_to_objectlog(self): content = ICMSContent('http://xml.zeit.de/online/2007/01/Somalia') info = IPublishInfo(content) self.assertFalse(info.published) info.urgent = True publish = IPublish(content).publish() transaction.commit() with self.assertRaises(Exception) as err: publish.get() transaction.begin() self.assertEqual(self.error, str(err.exception)) self.assertIn(self.error, [ zope.i18n.interpolate(m, m.mapping) for m in get_object_log(content) ])
def test_sets_first_paragraph_and_publishes(self): self.publisher.send('mytext', 'http://zeit.de/foo') zeit.workflow.testing.run_publish( zeit.cms.workflow.interfaces.PRIORITY_HIGH) article = self.repository['foo'] self.assertEqual(True, IPublishInfo(article).published) self.assertEllipsis( '<p...><a href="http://zeit.de/foo">mytext</a></p>', lxml.etree.tostring(IEditableBody(article).values()[0].xml))
def test_publish_via_celery_end_to_end(self): content = ICMSContent('http://xml.zeit.de/online/2007/01/Somalia') info = IPublishInfo(content) self.assertFalse(info.published) info.urgent = True publish = IPublish(content).publish() transaction.commit() self.assertEqual('Published.', publish.get()) transaction.begin() self.assertEllipsis( """\ Running job ... Publishing http://xml.zeit.de/online/2007/01/Somalia ... Done http://xml.zeit.de/online/2007/01/Somalia (...s)...""", self.log.getvalue()) self.assertIn('Published', get_object_log(content))
def update(self): if self.bcobj.skip_import: return True self._update() self._handle_images() if self.bcobj.state == 'ACTIVE': IPublish(self.cmsobj).publish(background=False) else: log.info('Deactivating %s', self.bcobj) if IPublishInfo(self.cmsobj).published: IPublish(self.cmsobj).retract(background=False)
def delete(self): if not isinstance(self.bcobj, DeletedVideo): return False elif self.cmsobj is None: # Deleted in BC and no CMS object: we're done. return True log.info('Deleting %s', self.bcobj) if IPublishInfo(self.cmsobj).published: IPublish(self.cmsobj).retract(background=False) del self.bcobj.__parent__[self.bcobj.id] return True
def test_delete_button_is_displayed_for_folder_without_published_objects( self): folder = self.repository['testing'] folder['foo'] = ExampleContentType() self.assertFalse(IPublishInfo(folder).published) browser = testing.Browser(self.layer['wsgi_app']) browser.login('producer', 'producerpw') browser.open('http://*****:*****@@delete.html') url = link.url.split("'")[1] # embedded in lightbox javascript browser.open(url) browser.getControl('Delete') # 'Delete' button exists
def add(self, object, container=None): super(Add, self).add(object, container) zeit.content.article.interfaces.IBreakingNews( self._created_object).is_breaking = True # We need to check out the new article so that AfterCheckout events are # run (which e.g. set default values of ICommonMetadata fields), but # the user won't want to edit anything right now, so we check in # immediately (and redirect to a view that triggers publishing). self._created_object = ICheckinManager(self._created_object).checkin() self._checked_out = False IPublishInfo(self._created_object).urgent = True
def test_multiple_created_articles_push_with_auhtor_template(self): from zeit.content.article.article import Article from zeit.cms.workflow.interfaces import IPublish, IPublishInfo content = Article() content.title = 'bar' zope.event.notify(ObjectCreatedEvent(content)) self.repository['bar'] = content IPublishInfo(self.repository['bar']).urgent = True IPublishInfo(self.repository['foo']).urgent = True IPublish(content).publish_multiple( [self.repository['foo'], self.repository['bar']]) calls = zope.component.getUtility(zeit.push.interfaces.IPushNotifier, name='urbanairship').calls self.assertEqual(calls[0][1], 'http://www.zeit.de/foo') self.assertEqual(calls[0][2].get('enabled'), True) self.assertEqual(calls[0][2].get('type'), 'mobile') self.assertEqual(calls[0][2].get('payload_template'), 'authors.json') self.assertEqual(calls[1][1], 'http://www.zeit.de/bar') self.assertEqual(calls[1][2].get('enabled'), True) self.assertEqual(calls[1][2].get('type'), 'mobile') self.assertEqual(calls[1][2].get('payload_template'), 'authors.json')
def test_error_during_publish_multiple_is_written_to_objectlog(self): c1 = ICMSContent('http://xml.zeit.de/online/2007/01/Flugsicherheit') c2 = ICMSContent('http://xml.zeit.de/online/2007/01/Saarland') i1 = IPublishInfo(c1) i2 = IPublishInfo(c2) self.assertFalse(i1.published) self.assertFalse(i2.published) i1.urgent = True i2.urgent = True publish = IPublish(c1).publish_multiple([c1, c2]) transaction.commit() with self.assertRaises(Exception) as err: publish.get() transaction.begin() self.assertEqual("Error during publish/retract: ScriptError: ('', 1)", str(err.exception)) self.assertIn( "Error during publish/retract: ScriptError: ('', 1)", [zope.i18n.interpolate(m, m.mapping) for m in get_object_log(c1)]) self.assertIn( "Error during publish/retract: ScriptError: ('', 1)", [zope.i18n.interpolate(m, m.mapping) for m in get_object_log(c2)])
def test_publish_multiple_via_celery_end_to_end(self): c1 = ICMSContent('http://xml.zeit.de/online/2007/01/Flugsicherheit') c2 = ICMSContent('http://xml.zeit.de/online/2007/01/Saarland') i1 = IPublishInfo(c1) i2 = IPublishInfo(c2) self.assertFalse(i1.published) self.assertFalse(i2.published) i1.urgent = True i2.urgent = True publish = IPublish(c1).publish_multiple([c1, c2]) transaction.commit() self.assertEqual('Published.', publish.get()) transaction.begin() self.assertEllipsis( """\ Running job ... for http://xml.zeit.de/online/2007/01/Flugsicherheit, http://xml.zeit.de/online/2007/01/Saarland Publishing http://xml.zeit.de/online/2007/01/Flugsicherheit, http://xml.zeit.de/online/2007/01/Saarland ... Done http://xml.zeit.de/online/2007/01/Flugsicherheit, http://xml.zeit.de/online/2007/01/Saarland (...s)""", self.log.getvalue()) self.assertIn('Published', get_object_log(c1)) self.assertIn('Published', get_object_log(c2))
def test_publishes_and_retracts_multiple_objects_in_single_script_call( self): c1 = zeit.cms.interfaces.ICMSContent( 'http://xml.zeit.de/online/2007/01/Somalia') c2 = zeit.cms.interfaces.ICMSContent( 'http://xml.zeit.de/online/2007/01/eta-zapatero') IPublishInfo(c1).urgent = True IPublishInfo(c2).urgent = True with mock.patch('zeit.workflow.publish.PublishTask' '.call_publish_script') as script: IPublish(self.repository).publish_multiple([c1, c2], async=False) script.assert_called_with([ 'work/online/2007/01/Somalia', 'work/online/2007/01/eta-zapatero' ]) self.assertTrue(IPublishInfo(c1).published) self.assertTrue(IPublishInfo(c2).published) with mock.patch('zeit.workflow.publish.RetractTask' '.call_retract_script') as script: IPublish(self.repository).retract_multiple([c1, c2], async=False) script.assert_called_with([ 'work/online/2007/01/Somalia', 'work/online/2007/01/eta-zapatero' ]) self.assertFalse(IPublishInfo(c1).published) self.assertFalse(IPublishInfo(c2).published)
def test_displays_last_published_information(self): article = zeit.cms.interfaces.ICMSContent( 'http://xml.zeit.de/online/2007/01/Somalia') IContentWorkflow(article).urgent = True IPublish(article).publish() IPublishInfo(article).date_last_published = datetime.datetime( 2013, 7, 2, 9, 31, 24, tzinfo=pytz.utc) b = self.browser b.open('http://localhost/++skin++vivi/repository' '/online/2007/01/Somalia/@@checkout') b.open('@@contents') self.assertEllipsis( '...last published at...02.07.2013...on...11:31...by' '...zope.user...', b.contents)