Exemplo n.º 1
0
    def test_trashing_and_restoring_updates_modified_date(self):
        self.grant('Site Administrator')

        created = datetime(2011, 1, 1, 1, 1, 1)
        trashed = datetime(2022, 2, 2, 2, 2, 2)
        restored = datetime(2033, 3, 3, 3, 3, 3)

        with freeze(created):
            folder = create(Builder('folder'))
            subfolder = create(Builder('folder').within(folder))

        self.assert_modified_date(created, folder)
        self.assert_modified_date(created, subfolder)

        with freeze(trashed):
            Trasher(folder).trash()

        self.assert_modified_date(trashed, folder)
        self.assert_modified_date(trashed, subfolder)

        with freeze(restored):
            Trasher(folder).restore()

        self.assert_modified_date(restored, folder)
        self.assert_modified_date(restored, subfolder)
Exemplo n.º 2
0
    def test_trashing_and_restoring_parent_of_a_trashed_content_does_not_influence_child(
            self):
        """
        Given a subpage is trashed.
        When the parent page is also trashed, and later restored, the subpage should still
        be trashed.
        The subpage should also stay restorable.
        """
        self.grant('Site Administrator')

        folder = create(Builder('folder'))
        foo = create(Builder('folder').within(folder))
        bar = create(Builder('folder').within(folder))

        self.assert_provides(folder, None)
        self.assert_provides(foo, None)
        self.assert_provides(bar, None)

        Trasher(foo).trash()
        self.assert_provides(folder, None)
        self.assert_provides(foo, ITrashed, IRestorable)
        self.assert_provides(bar, None)

        Trasher(folder).trash()
        self.assert_provides(folder, ITrashed, IRestorable)
        self.assert_provides(foo, ITrashed, IRestorable)
        self.assert_provides(bar, ITrashed)

        Trasher(folder).restore()
        self.assert_provides(folder, None)
        self.assert_provides(foo, ITrashed, IRestorable)
        self.assert_provides(bar, None)
Exemplo n.º 3
0
    def test_is_restorable_when_trashed(self):
        self.grant('Site Administrator')

        folder = create(Builder('folder'))
        self.assertFalse(Trasher(folder).is_restorable())

        Trasher(folder).trash()
        self.assertTrue(Trasher(folder).is_restorable())
Exemplo n.º 4
0
    def test_cannot_restore_content_when_parent_is_trashed(self):
        self.grant('Site Administrator')

        folder = create(Builder('folder'))
        subfolder = create(Builder('folder').within(folder))
        Trasher(folder).trash()

        with self.assertRaises(NotRestorable):
            Trasher(subfolder).restore()
Exemplo n.º 5
0
    def test_catalog_is_updated_when_restoring_content(self):
        self.grant('Site Administrator')

        folder = create(Builder('folder'))
        subfolder = create(Builder('folder').within(folder))

        self.assertFalse(self.get_catalog_indexdata(folder).get('trashed'))
        self.assertNotIn(
            ITrashed.__identifier__,
            self.get_catalog_indexdata(folder).get('object_provides'))
        self.assertNotIn(
            IRestorable.__identifier__,
            self.get_catalog_indexdata(folder).get('object_provides'))

        self.assertFalse(self.get_catalog_indexdata(subfolder).get('trashed'))
        self.assertNotIn(
            ITrashed.__identifier__,
            self.get_catalog_indexdata(subfolder).get('object_provides'))
        self.assertNotIn(
            IRestorable.__identifier__,
            self.get_catalog_indexdata(subfolder).get('object_provides'))

        Trasher(folder).trash()
        self.assertTrue(self.get_catalog_indexdata(folder).get('trashed'))
        self.assertIn(
            ITrashed.__identifier__,
            self.get_catalog_indexdata(folder).get('object_provides'))
        self.assertIn(
            IRestorable.__identifier__,
            self.get_catalog_indexdata(folder).get('object_provides'))

        self.assertTrue(self.get_catalog_indexdata(subfolder).get('trashed'))
        self.assertIn(
            ITrashed.__identifier__,
            self.get_catalog_indexdata(subfolder).get('object_provides'))
        self.assertNotIn(
            IRestorable.__identifier__,
            self.get_catalog_indexdata(subfolder).get('object_provides'))

        Trasher(folder).restore()
        self.assertFalse(self.get_catalog_indexdata(folder).get('trashed'))
        self.assertNotIn(
            ITrashed.__identifier__,
            self.get_catalog_indexdata(folder).get('object_provides'))
        self.assertNotIn(
            IRestorable.__identifier__,
            self.get_catalog_indexdata(folder).get('object_provides'))

        self.assertFalse(self.get_catalog_indexdata(subfolder).get('trashed'))
        self.assertNotIn(
            ITrashed.__identifier__,
            self.get_catalog_indexdata(subfolder).get('object_provides'))
        self.assertNotIn(
            IRestorable.__identifier__,
            self.get_catalog_indexdata(subfolder).get('object_provides'))
Exemplo n.º 6
0
    def test_restorable_content_can_be_restored(self):
        self.grant('Site Administrator')

        folder = create(Builder('folder'))
        self.assert_provides(folder, None)

        Trasher(folder).trash()
        self.assert_provides(folder, IRestorable, ITrashed)

        Trasher(folder).restore()
        self.assert_provides(folder, None)
Exemplo n.º 7
0
    def test_children_are_restored_correctly(self):
        self.grant('Site Administrator')

        folder = create(Builder('folder'))
        subfolder = create(Builder('folder').within(folder))
        self.assert_provides(folder, None)
        self.assert_provides(subfolder, None)

        Trasher(folder).trash()
        self.assert_provides(folder, IRestorable, ITrashed)
        self.assert_provides(subfolder, ITrashed)

        Trasher(folder).restore()
        self.assert_provides(folder, None)
        self.assert_provides(subfolder, None)
Exemplo n.º 8
0
    def test_restore_trashed_content(self, browser):
        self.grant('Site Administrator')

        folder = create(Builder('folder').titled(u'My Folder'))
        with freeze(datetime(2011, 1, 1)):
            Trasher(folder).trash()

        self.assert_provides(folder, IRestorable, ITrashed)

        transaction.commit()
        browser.login().open().click_on('Trash')

        self.assertEquals([{
            'Last modified': 'Jan 01, 2011 12:00 AM',
            'Type': self.type_label,
            'Title': 'My Folder http://nohost/plone/my-folder',
            '': ''
        }],
                          browser.css('.trash-table').first.dicts())

        browser.css('.trash-table').find('Restore').first.click()
        statusmessages.assert_message(
            'The content "My Folder" has been restored.')
        self.assertEqual(folder.absolute_url(), browser.url)

        transaction.begin()
        self.assert_provides(folder, None)
Exemplo n.º 9
0
    def test_lists_only_restorable_content(self, browser):
        self.grant('Site Administrator')

        create(Builder('folder').titled(u'Keep that'))
        parent = create(Builder('folder').titled(u'Parent'))
        folder = create(
            Builder('folder').titled(u'Delete that').within(parent))
        create(
            Builder('folder').titled(u'Child of folder to be deleted').within(
                folder))

        with freeze(datetime(2016, 12, 15, 17, 9)):
            Trasher(folder).trash()

        transaction.commit()
        browser.login().open().click_on('Trash')
        self.assertEquals('trash', plone.view())

        self.assertEquals([{
            'Last modified': 'Dec 15, 2016 05:09 PM',
            'Type': self.type_label,
            'Title': 'Delete that http://nohost/plone/parent/delete-that',
            '': ''
        }],
                          browser.css('.trash-table').first.dicts())
Exemplo n.º 10
0
    def restore(self, REQUEST, uuid):
        """Restore an item by uid.
        """
        catalog = getToolByName(self.context, 'portal_catalog')
        brains = catalog({'UID': uuid, 'trashed': True})
        if len(brains) != 1:
            raise BadRequest()

        obj = brains[0].getObject()
        parent = aq_parent(aq_inner(obj))
        if ITrashed.providedBy(parent):
            IStatusMessage(self.request).addStatusMessage(_(
                u'statusmessage_content_restore_error_parent_trashed',
                default=
                (u'"${title}" cannot be restored because the parent container'
                 u' "${parent}" is also trashed.'
                 u' You need to restore the parent first.'),
                mapping={
                    u'title': safe_unicode(obj.Title()),
                    u'parent': safe_unicode(parent.Title())
                }),
                                                          type='error')
            return self.request.response.redirect(self.context.absolute_url() +
                                                  '/trash')

        trasher = Trasher(obj)
        if not trasher.is_restorable():
            IStatusMessage(self.request).addStatusMessage(_(
                u'statusmessage_content_restore_not_allowed',
                default=
                (u'You are not allowed to restore "${title}".'
                 u' You may need to change the workflow state of the parent content.'
                 ),
                mapping={u'title': safe_unicode(obj.Title())}),
                                                          type='error')
            return self.request.response.redirect(self.context.absolute_url() +
                                                  '/trash')

        trasher.restore()
        IStatusMessage(self.request).addStatusMessage(_(
            u'statusmessage_content_restored',
            default=u'The content "${title}" has been restored.',
            mapping={u'title': safe_unicode(obj.Title())}),
                                                      type='info')

        target_url = obj.restrictedTraverse('@@plone_context_state').view_url()
        self.request.response.redirect(target_url)
Exemplo n.º 11
0
    def test_marks_trashed_page_as_trashed_and_restorable(self):
        self.grant('Contributor')

        folder = create(Builder('folder'))
        self.assert_provides(folder, None)

        Trasher(folder).trash()
        self.assert_provides(folder, IRestorable, ITrashed)
Exemplo n.º 12
0
 def test_restore_redirects_to_view_for_files(self, browser):
     self.grant('Site Administrator')
     doc = create(Builder('file').with_dummy_content())
     Trasher(doc).trash()
     transaction.commit()
     browser.login().open(view='trash').click_on('Restore')
     self.assertEquals('http://nohost/plone/{}/view'.format(doc.getId()),
                       browser.url)
Exemplo n.º 13
0
 def test_plone_contentItems_does_not_return_trashed_content(self):
     """A Plone site's contentItems should not return trashed content.
     """
     self.grant('Contributor')
     foo = create(Builder('folder').titled(u'Foo'))
     self.assertIn(('foo', foo), self.portal.contentItems())
     Trasher(foo).trash()
     self.assertNotIn(('foo', foo), self.portal.contentItems())
Exemplo n.º 14
0
 def test_plone_objectItems_returns_trashed_content(self):
     """A Plone site's objectItems should return trashed content.
     """
     self.grant('Contributor')
     foo = create(Builder('folder').titled(u'Foo'))
     self.assertIn(('foo', foo), list(self.portal.objectItems()))
     Trasher(foo).trash()
     self.assertIn(('foo', foo), list(self.portal.objectItems()))
Exemplo n.º 15
0
    def test_events_are_fired(self):
        self.grant('Site Administrator')
        folder = create(Builder('folder'))
        fired_events = []
        registerHandler = self.portal.getSiteManager().registerHandler

        @registerHandler
        @adapter(Interface, IBeforeObjectTrashedEvent)
        def before_trashing(object, event):
            self.assertEqual(folder, object)
            self.assertEqual(folder, event.object)
            self.assertFalse(ITrashed.providedBy(object))
            fired_events.append(type(event).__name__)

        @registerHandler
        @adapter(Interface, IObjectTrashedEvent)
        def after_trashing(object, event):
            self.assertEqual(folder, object)
            self.assertEqual(folder, event.object)
            self.assertTrue(ITrashed.providedBy(object))
            fired_events.append(type(event).__name__)

        @registerHandler
        @adapter(Interface, IBeforeObjectRestoredEvent)
        def before_restoring(object, event):
            self.assertEqual(folder, object)
            self.assertEqual(folder, event.object)
            self.assertTrue(ITrashed.providedBy(object))
            fired_events.append(type(event).__name__)

        @registerHandler
        @adapter(Interface, IObjectRestoredEvent)
        def after_restoring(object, event):
            self.assertEqual(folder, object)
            self.assertEqual(folder, event.object)
            self.assertFalse(ITrashed.providedBy(object))
            fired_events.append(type(event).__name__)

        Trasher(folder).trash()
        self.assertEquals(['BeforeObjectTrashedEvent', 'ObjectTrashedEvent'],
                          fired_events)
        fired_events[:] = []
        Trasher(folder).restore()
        self.assertEquals(['BeforeObjectRestoredEvent', 'ObjectRestoredEvent'],
                          fired_events)
Exemplo n.º 16
0
    def test_returns_trashed_content_when_explicitly_queried_for(self):
        self.grant('Contributor')

        create(Builder('folder').titled(u'Foo'))
        Trasher(create(Builder('folder').titled(u'Bar'))).trash()
        self.assert_catalog_result({'Foo'}, query={})
        self.assert_catalog_result({'Foo', 'Bar'}, query={'trashed': None})
        self.assert_catalog_result({'Bar'}, query={'trashed': True})
        self.assert_catalog_result({'Foo'}, query={'trashed': False})
Exemplo n.º 17
0
def manage_trashObjects(self, ids=None, REQUEST=None):
    """Marks objects as trashed.
    """
    if ids is None:
        ids = []
    if isinstance(ids, basestring):
        ids = [ids]
    for id_ in ids:
        Trasher(self._getOb(id_)).trash()
Exemplo n.º 18
0
    def test_filters_trashed_content_by_default(self):
        self.grant('Contributor')

        create(Builder('folder').titled(u'Foo'))
        bar = create(Builder('folder').titled(u'Bar'))
        self.assert_catalog_result({'Bar', 'Foo'})

        Trasher(bar).trash()
        self.assert_catalog_result({'Foo'})
Exemplo n.º 19
0
 def test_listFolderContents_does_not_return_trashed_content(self):
     """A folder's listFolderContents should not return trashed content.
     """
     self.grant('Contributor')
     container = create(Builder('folder').titled(u'Container'))
     foo = create(Builder('folder').titled(u'Foo').within(container))
     bar = create(Builder('folder').titled(u'Bar').within(container))
     self.assertEqual([foo, bar], container.listFolderContents())
     Trasher(foo).trash()
     self.assertEqual([bar], container.listFolderContents())
Exemplo n.º 20
0
    def test_is_restorable_respectsIIsRestoreAllowedAdapter(self):
        response = {'allowed': True, 'called': 0}
        self.grant('Site Administrator')

        folder = create(Builder('folder'))
        Trasher(folder).trash()

        @implementer(IIsRestoreAllowedAdapter)
        @adapter(Interface, Interface)
        def is_restore_allowed(context, request):
            response['called'] += 1
            return response['allowed']

        getSiteManager().registerAdapter(is_restore_allowed)

        self.assertTrue(Trasher(folder).is_restorable())
        response['allowed'] = False
        self.assertFalse(Trasher(folder).is_restorable())
        self.assertEqual(2, response['called'])
Exemplo n.º 21
0
    def test_marks_children_of_trashed_folder_only_as_trashed(self):
        self.grant('Contributor')

        folder = create(Builder('folder'))
        subfolder = create(Builder('folder').within(folder))
        self.assert_provides(folder, None)
        self.assert_provides(subfolder, None)

        Trasher(folder).trash()
        self.assert_provides(folder, IRestorable, ITrashed)
        self.assert_provides(subfolder, ITrashed)
Exemplo n.º 22
0
 def test_folder_contentItems_does_not_return_trashed_content(self):
     """A folder's contentItems should not return trashed content.
     """
     self.grant('Contributor')
     container = create(Builder('folder').titled(u'Container'))
     foo = create(Builder('folder').titled(u'Foo').within(container))
     bar = create(Builder('folder').titled(u'Bar').within(container))
     self.assertEqual([('foo', foo), ('bar', bar)],
                      container.contentItems())
     Trasher(foo).trash()
     self.assertEqual([('bar', bar)], container.contentItems())
Exemplo n.º 23
0
    def test_allow_Manager_to_browse_trashed_content_with_status_message(self, browser):
        self.grant('Manager')

        folder = create(Builder('folder').titled(u'Fancy Folder'))
        browser.login()
        browser.open(folder)

        Trasher(folder).trash()
        transaction.commit()
        browser.open(folder)

        statusmessages.assert_message('The content "Fancy Folder" is trashed.')
Exemplo n.º 24
0
    def test_empty_trash_when_parent_and_child_are_both_trashed(self, browser):
        """Regression test: when trying to delete a child but the parent was deleted
        bevore, an exception is raised.
        Solution: do not delete children and parents in the same set; just delete parents,
        which is recursive anyway.
        """
        self.grant('Site Administrator')

        parent = create(Builder('folder').titled(u'Parent'))
        child = create(Builder('folder').titled(u'Child').within(parent))

        Trasher(child).trash()
        Trasher(parent).trash()
        transaction.commit()

        browser.login().open().click_on('Trash')
        self.assertEquals('Trash', plone.first_heading())

        self.assertIn('parent', self.portal.objectIds())
        browser.click_on('Clean trash').click_on('Delete')
        self.assertNotIn('parent', self.portal.objectIds())
Exemplo n.º 25
0
    def test_restore_requires_permission(self):
        self.grant('Contributor')

        parent = create(Builder('folder'))
        parent.manage_permission('Restore trashed content',
                                 roles=[],
                                 acquire=False)

        folder = create(Builder('folder').within(parent))
        Trasher(folder).trash()
        self.assert_provides(folder, IRestorable, ITrashed)

        with self.assertRaises(Unauthorized):
            Trasher(folder).restore()

        self.assert_provides(folder, IRestorable, ITrashed)

        parent.manage_permission('Restore trashed content',
                                 roles=['Contributor'],
                                 acquire=False)
        Trasher(folder).restore()
        self.assert_provides(folder, None)
Exemplo n.º 26
0
    def test_trashed_download_view_not_accessible(self, browser):
        self.grant('Contributor')
        folder = create(Builder('folder'))
        file_ = create(Builder('file').within(folder).with_dummy_content())

        browser.login()
        browser.open(file_.absolute_url() + '/@@download/file/test.txt')

        Trasher(folder).trash()
        transaction.commit()

        with browser.expect_http_error(404):
            browser.open(file_.absolute_url() + '/@@download/file/test.txt')
Exemplo n.º 27
0
    def test_unrestrictedSearchResults_returns_all_items_by_default(self):
        """unrestrictedSearchResults must return all items by default, no matter whether
        they're trashed or not, because ftw.upgrade uses unrestrictedSearchResults
        and we want to make sure that all objects are migrated.
        """
        self.grant('Contributor')

        create(Builder('folder').titled(u'Foo'))
        Trasher(create(Builder('folder').titled(u'Bar'))).trash()
        catalog = getToolByName(self.portal, 'portal_catalog')
        self.assertItemsEqual(
            ('Foo', 'Bar'),
            [brain.Title for brain in catalog.unrestrictedSearchResults()])
Exemplo n.º 28
0
    def test_not_restorable_when_parent_is_trashed_too(self):
        self.grant('Site Administrator')

        folder = create(Builder('folder'))
        subfolder = create(Builder('folder').within(folder))
        self.assertFalse(Trasher(folder).is_restorable())
        self.assertFalse(Trasher(subfolder).is_restorable())

        Trasher(subfolder).trash()
        self.assertFalse(Trasher(folder).is_restorable())
        self.assertTrue(Trasher(subfolder).is_restorable())

        Trasher(folder).trash()
        self.assertTrue(Trasher(folder).is_restorable())
        self.assertFalse(Trasher(subfolder).is_restorable())
Exemplo n.º 29
0
    def test_error_message_when_parent_is_trashed(self, browser):
        self.grant('Site Administrator')

        parent = create(Builder('folder').titled(u'Parent'))
        child = create(Builder('folder').titled(u'Child').within(parent))
        Trasher(parent).trash()
        Trasher(child).trash()
        self.assert_provides(parent, IRestorable, ITrashed)
        self.assert_provides(child, IRestorable, ITrashed)
        transaction.commit()

        browser.login().open().click_on('Trash')
        table = browser.css('table.trash-table')
        table.xpath('//*[text()="Child"]').first.parent('tr').find(
            'Restore').click()

        statusmessages.assert_message(
            '"Child" cannot be restored because the parent container "Parent" is also'
            ' trashed. You need to restore the parent first.')

        transaction.begin()
        self.assert_provides(parent, IRestorable, ITrashed)
        self.assert_provides(child, IRestorable, ITrashed)
Exemplo n.º 30
0
    def test_error_message_when_restore_not_allowed(self, browser):
        self.grant('Site Administrator')

        parent = create(Builder('folder').titled(u'Parent'))
        folder = create(Builder('folder').titled(u'My Folder').within(parent))
        Trasher(folder).trash()
        parent.manage_permission('Add portal content', roles=[], acquire=False)
        transaction.commit()

        browser.login().open().click_on('Trash').click_on('Restore')
        statusmessages.assert_message(
            'You are not allowed to restore "My Folder".'
            ' You may need to change the workflow state of the parent content.'
        )

        transaction.begin()
        self.assert_provides(folder, IRestorable, ITrashed)
 def test_trashed_textblock_is_not_sl_contentish(self):
     block = create(Builder('sl textblock')
                    .within(create(Builder('sl content page'))))
     trasher = Trasher(block)
     trasher.trash()
     self.assertFalse(is_sl_contentish(block))