class TestPloneRootLoginURL(unittest.TestCase):

    layer = PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING

    def setUp(self):
        self.portal = self.layer['portal']
        self.app = self.layer['app']
        self.browser = Browser(self.app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization',
            'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD)
        )

    def test_normal_redirect(self):
        url = '/@@plone-root-login?came_from=%s' % self.portal.absolute_url()
        self.browser.open(self.app.absolute_url() + url)
        self.assertNotEqual(self.browser.url, None)
        self.assertEqual(self.browser.url,
                         self.portal.absolute_url())

    def test_attacker_redirect(self):
        attackers = (
            'http://attacker.com',
            '\\attacker.com',
        )
        for attacker in attackers:
            url = '@@plone-root-login?came_from=%s' % attacker
            with self.assertRaises(HostNotAllowed):
                self.browser.open(self.app.absolute_url() + url)
Esempio n. 2
0
class DocumentFunctionalTest(unittest.TestCase):

    layer = PLONE_APP_CONTENTTYPES_FUNCTIONAL_TESTING

    def setUp(self):
        app = self.layer['app']
        self.portal = self.layer['portal']
        self.request = self.layer['request']
        self.portal_url = self.portal.absolute_url()
        self.browser = Browser(app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization', 'Basic {0}:{1}'.format(
                SITE_OWNER_NAME,
                SITE_OWNER_PASSWORD,
            ))

    def test_add_document(self):
        self.browser.open(self.portal_url)
        self.browser.getLink(url='http://nohost/plone/++add++Document').click()
        widget = 'form.widgets.IDublinCore.title'
        self.browser.getControl(name=widget).value = 'My document'
        widget = 'form.widgets.IDublinCore.description'
        self.browser.getControl(name=widget).value = 'This is my document.'
        widget = 'form.widgets.IRichTextBehavior.text'
        self.browser.getControl(name=widget).value = 'Lorem Ipsum'
        widget = 'form.widgets.IShortName.id'
        self.browser.getControl(name=widget).value = 'my-special-document'
        self.browser.getControl('Save').click()
        self.assertTrue(self.browser.url.endswith('my-special-document/view'))
        self.assertTrue('My document' in self.browser.contents)
        self.assertTrue('This is my document' in self.browser.contents)
        self.assertTrue('Lorem Ipsum' in self.browser.contents)
Esempio n. 3
0
    def prepare_for_acquisition_tests(self):
        """create content and an alternate authenticated browser session

        creates the following content structure:

        |-- f1
        |   |-- test
        |-- test
        """
        # create a page at the root and one nested with the same id.
        p1 = self.portal.invokeFactory(type_name='Document',
                                       id='test',
                                       title='Test Page at Root')
        folder_1 = self.portal['f1']
        p2 = folder_1.invokeFactory(type_name='Document',
                                    id='test',
                                    title='Test Page in Folder')
        contained_test_page = folder_1[p2]

        transaction.commit()

        # create an alternate browser also logged in with manager
        browser_2 = Browser(self.layer['app'])
        browser_2.handleErrors = False
        browser_2.addHeader('Authorization',
                            'Basic {}:{}'.format(TEST_USER_NAME, 'secret'))

        # return the id of the root page, the nested page itself, and the
        # alternate browser
        return p1, contained_test_page, browser_2
Esempio n. 4
0
class TestCSRF(unittest.TestCase):
    layer = PROTECT_FUNCTIONAL_TESTING

    def setUp(self):
        self.portal = self.layer['portal']
        self.browser = Browser(self.layer['app'])
        self.request = self.layer['request']
        self.browser.addHeader(
            'Authorization',
            'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)
        )

    def test_change_password_on_root_does_not_throw_other_csrf_protection(
            self
    ):
        self.browser.open(
            '%s/acl_users/users/manage_users?user_id=%s&passwd=1' % (
                self.layer['app'].absolute_url(), SITE_OWNER_NAME
            )
        )
        self.browser.getControl(name='password').value = SITE_OWNER_PASSWORD
        self.browser.getControl(name='confirm').value = SITE_OWNER_PASSWORD
        self.browser.getForm(action='manage_updateUserPassword').submit()
        self.assertEquals(
            self.browser.url,
            '%s/acl_users/users/manage_users?'
            'manage_tabs_message=password+updated' % (
                self.layer['app'].absolute_url()
            )
        )
Esempio n. 5
0
class ConflictTests(TestCase):

    layer = LEGACY_COLLECTIVE_SOLR_FUNCTIONAL_TESTING

    def setUp(self):
        activateAndReindex(self.layer["portal"])
        commit()
        self.browser = Browser(self.layer["app"])
        self.browser.addHeader(
            "Authorization",
            "Basic %s:%s" % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD))

    def test_retry_on_conflict(self):
        """This tests transaction handling when indexing in Solr, or more
        specifically properly aborting a transaction.  To do this we'll try to
        create some content and fake a `ConflictError` shortly before the
        transaction completes.  The publisher will catch it and retry, but
        while doing so the object will get a different UID than the first time.
        Without being able to abort the transaction Solr would receive two sets
        of data and consequently return two results when searching for this
        particular piece of content later on.
        """
        self.browser.open(self.layer["portal"].absolute_url())
        self.browser.getLink("Page").click()
        self.browser.getControl("Title", index=0).value = "Foo"
        component.provideHandler(raise_on_first_add,
                                 (Interface, IObjectCreatedEvent))
        self.browser.getControl("Save").click()
        self.assertEqual(len(UIDS), 2)
        self.assertEqual(len(solrSearchResults(SearchableText="Foo")), 1)

        sm = component.getSiteManager()
        sm.unregisterHandler(raise_on_first_add,
                             (Interface, IObjectCreatedEvent))
class LinkFunctionalTest(unittest.TestCase):

    layer = PLONE_APP_CONTENTTYPES_FUNCTIONAL_TESTING

    def setUp(self):
        app = self.layer['app']
        self.portal = self.layer['portal']
        self.request = self.layer['request']
        self.portal_url = self.portal.absolute_url()
        self.browser = Browser(app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization',
            'Basic {0}:{1}'.format(SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)
        )

    def test_add_link(self):
        self.browser.open(self.portal_url)
        self.browser.getLink('Link').click()
        self.browser.getControl(name='form.widgets.IDublinCore.title')\
            .value = 'My link'
        self.browser.getControl(name='form.widgets.IDublinCore.description')\
            .value = 'This is my link.'
        self.browser.getControl(name='form.widgets.IShortName.id')\
            .value = 'my-special-link'
        self.browser.getControl(name='form.widgets.remoteUrl.external')\
            .value = 'https://plone.org'
        self.browser.getControl('Save').click()

        self.assertTrue(self.browser.url.endswith('my-special-link/view'))
        self.assertTrue('My link' in self.browser.contents)
        self.assertTrue('This is my link' in self.browser.contents)
class MarkupControlPanelFunctionalTest(unittest.TestCase):
    """Make sure changes in the markup control panel are properly
    stored in plone.app.registry.
    """

    layer = PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING

    def setUp(self):
        self.app = self.layer['app']
        self.portal = self.layer['portal']
        self.portal_url = self.portal.absolute_url()
        self.browser = Browser(self.app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization', 'Basic %s:%s' % (
                SITE_OWNER_NAME,
                SITE_OWNER_PASSWORD,
            ))

    def test_markup_control_panel_link(self):
        self.browser.open("%s/@@overview-controlpanel" % self.portal_url)
        self.browser.getLink('Markup').click()

    def test_markup_control_panel_backlink(self):
        self.browser.open("%s/@@markup-controlpanel" % self.portal_url)
        self.assertTrue("Content" in self.browser.contents)

    def test_markup_control_panel_sidebar(self):
        self.browser.open("%s/@@markup-controlpanel" % self.portal_url)
        self.browser.getLink('Site Setup').click()
        self.assertTrue(
            self.browser.url.endswith('/plone/@@overview-controlpanel'))

    def test_markup_controlpanel_view(self):
        view = getMultiAdapter((self.portal, self.portal.REQUEST),
                               name="markup-controlpanel")
        self.assertTrue(view())

    def test_default_type(self):
        self.browser.open("%s/@@markup-controlpanel" % self.portal_url)
        self.browser.getControl('Default format').value = ['text/plain']
        self.browser.getControl('Save').click()

        registry = getUtility(IRegistry)
        settings = registry.forInterface(IMarkupSchema, prefix='plone')
        self.assertEqual(settings.default_type, 'text/plain')

    def test_allowed_types(self):
        self.browser.open("%s/@@markup-controlpanel" % self.portal_url)
        self.browser.getControl(
            name='form.widgets.allowed_types:list').value = [
                'text/html', 'text/x-web-textile'
            ]
        self.browser.getControl('Save').click()

        registry = getUtility(IRegistry)
        settings = registry.forInterface(IMarkupSchema, prefix='plone')
        self.assertEqual(settings.allowed_types,
                         ('text/html', 'text/x-web-textile'))
class SearchControlPanelFunctionalTest(unittest.TestCase):
    """Test that changes in the search control panel are actually
    stored in the registry.
    """

    layer = PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING

    def setUp(self):
        self.app = self.layer['app']
        self.portal = self.layer['portal']
        self.portal_url = self.portal.absolute_url()
        self.browser = Browser(self.app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization', 'Basic %s:%s' % (
                SITE_OWNER_NAME,
                SITE_OWNER_PASSWORD,
            ))

    def test_search_control_panel_link(self):
        self.browser.open("%s/@@overview-controlpanel" % self.portal_url)
        self.browser.getLink('Search').click()

    def test_search_control_panel_backlink(self):
        self.browser.open("%s/@@search-controlpanel" % self.portal_url)
        self.assertTrue("General" in self.browser.contents)

    def test_search_control_panel_sidebar(self):
        self.browser.open("%s/@@search-controlpanel" % self.portal_url)
        self.browser.getLink('Site Setup').click()
        self.assertTrue(
            self.browser.url.endswith('/plone/@@overview-controlpanel'))

    def test_search_controlpanel_view(self):
        view = getMultiAdapter((self.portal, self.portal.REQUEST),
                               name="search-controlpanel")
        self.assertTrue(view())

    def test_enable_livesearch(self):
        self.browser.open("%s/@@search-controlpanel" % self.portal_url)
        self.browser.getControl('Enable LiveSearch').selected = True
        self.browser.getControl('Save').click()

        registry = getUtility(IRegistry)
        settings = registry.forInterface(ISearchSchema, prefix="plone")
        self.assertEqual(settings.enable_livesearch, True)

    def test_types_not_searched(self):
        self.browser.open("%s/@@search-controlpanel" % self.portal_url)
        self.browser.getControl(
            name='form.widgets.types_not_searched:list').value = [
                'Discussion Item', 'News Item'
            ]
        self.browser.getControl('Save').click()

        registry = getUtility(IRegistry)
        settings = registry.forInterface(ISearchSchema, prefix="plone")
        self.assertFalse('Discussion Item' in settings.types_not_searched)
        self.assertFalse('News Item Item' in settings.types_not_searched)
Esempio n. 9
0
 def getBrowser(self, loggedIn=True):
     transaction.commit()
     browser = Browser(self.app)
     if loggedIn:
         user = TEST_USER_NAME
         pwd = default_password
         browser.addHeader('Authorization', 'Basic %s:%s' % (user, pwd))
     return browser
Esempio n. 10
0
 def get_browser(self):
     browser = Browser(self.layer["app"])
     browser.handleErrors = False
     browser.addHeader(
         "Authorization",
         f"Basic {SITE_OWNER_NAME}:{SITE_OWNER_PASSWORD}",
     )
     return browser
Esempio n. 11
0
def get_browser(layer, auth=True):
    browser = Browser(layer["app"])
    browser.handleErrors = False
    if auth:
        api.user.create(
            username="******", password="******", email="*****@*****.**", roles=("Manager",)
        )
        transaction.commit()
        browser.addHeader("Authorization", "Basic adm:secret")
    return browser
Esempio n. 12
0
class FunctionalTestCase(IntegrationTestCase):
    layer = testing.FUNCTIONAL

    def setUp(self):
        super().setUp()
        self.browser = Browser(self.layer['app'])
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization',
            'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)
        )
Esempio n. 13
0
class TestRoot(unittest.TestCase, _BaseAutoTest):

    def setUp(self):
        self.portal = self.layer['portal']
        self.browser = Browser(self.layer['app'])
        self.request = self.layer['request']
        self.browser.addHeader(
            'Authorization',
            'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)
        )

    def open(self, path):
        self.browser.open(self.portal.aq_parent.absolute_url() + '/' + path)
Esempio n. 14
0
 def _get_browser(self):
     # Need to commit transaction, otherwise the browser does not
     # see anything.
     import transaction
     transaction.commit()
     # Set up browser
     app = self.layer['app']
     browser = Browser(app)
     browser.handleErrors = False
     browser.addHeader(
         'Authorization',
         'Basic {0}:{1}'.format(SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)
     )
     return browser
Esempio n. 15
0
class TableOfContentsBehaviorFunctionalTest(unittest.TestCase):

    layer = PLONE_APP_CONTENTTYPES_FUNCTIONAL_TESTING

    def setUp(self):
        app = self.layer['app']
        self.portal = self.layer['portal']
        self.request = self.layer['request']
        self.portal_url = self.portal.absolute_url()
        setRoles(self.portal, TEST_USER_ID, ['Contributor'])
        fti = DexterityFTI('tocdocument')
        self.portal.portal_types._setObject('tocdocument', fti)
        fti.klass = 'plone.dexterity.content.Item'
        fti.behaviors = ('plone.app.contenttypes.behaviors.tableofcontents.'
                         'ITableOfContents', )
        self.fti = fti
        alsoProvides(self.portal.REQUEST, IPloneAppContenttypesLayer)
        alsoProvides(self.request, IPloneAppContenttypesLayer)
        from plone.app.contenttypes.behaviors.tableofcontents \
            import ITableOfContents
        alsoProvides(self.request, ITableOfContents)
        self.portal.invokeFactory('tocdocument',
                                  id='tocdoc',
                                  title=u'Document with a table of contents')
        import transaction
        transaction.commit()
        # Set up browser
        self.browser = Browser(app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization', 'Basic {0}:{1}'.format(
                SITE_OWNER_NAME,
                SITE_OWNER_PASSWORD,
            ))

    def test_toc_in_edit_form(self):
        self.browser.open(self.portal_url + '/tocdoc/edit')
        self.assertTrue('Table of contents' in self.browser.contents)

    def test_toc_viewlet_shows_up(self):
        self.browser.open(self.portal_url + '/tocdoc/edit')
        toc_ctl = self.browser.getControl(
            name='form.widgets.ITableOfContents.table_of_contents:list')
        toc_ctl.value = [
            u'selected',
        ]
        # Submit form
        self.browser.getControl('Save').click()
        self.assertTrue('<section id="document-toc"' in self.browser.contents)
Esempio n. 16
0
class ProductsCMFPloneSetupTest(unittest.TestCase):

    layer = PLONE_APP_CONTENTTYPES_FUNCTIONAL_TESTING

    def setUp(self):
        app = self.layer['app']
        self.portal = self.layer['portal']
        self.request = self.layer['request']
        self.portal_url = self.portal.absolute_url()

        self.browser = Browser(app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization',
            'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)
        )
        setRoles(self.portal, TEST_USER_ID, ['Manager'])

    def test_sitemap(self):
        self.portal.invokeFactory('Document', 'doc1', title="Document 1")
        self.portal.invokeFactory('Document', 'doc2', title="Document 2")
        self.portal.invokeFactory('Document', 'doc3', title="Document 3")
        transaction.commit()
        self.browser.open(self.portal_url + '/sitemap')
        output = lxml.html.fromstring(self.browser.contents)
        sitemap = output.xpath("//ul[@id='portal-sitemap']")[0].text_content()

        self.assertTrue('Document 1' in sitemap)
        self.assertTrue('Document 2' in sitemap)
        self.assertTrue('Document 3' in sitemap)

    def test_sitemap_nested(self):
        self.portal.invokeFactory('Folder', 'folder1', title='Folder 1')
        self.portal.invokeFactory('Document', 'doc1', title='Document 1')
        self.portal.invokeFactory('Folder', 'folder2', title='Folder 2')
        self.portal.folder1.invokeFactory(
            'Document', 'doc12', title='Document 12')
        transaction.commit()

        self.browser.open(self.portal_url + '/sitemap')
        output = lxml.html.fromstring(self.browser.contents)
        sitemap = output.xpath("//ul[@id='portal-sitemap']")[0].text_content()

        self.assertTrue('Folder 1' in sitemap)
        self.assertTrue('Document 1' in sitemap)
        self.assertTrue('Folder 2' in sitemap)
        self.assertTrue('Document 12' in sitemap)
Esempio n. 17
0
class NewsItemFunctionalTest(unittest.TestCase):

    layer = PLONE_APP_CONTENTTYPES_FUNCTIONAL_TESTING

    def setUp(self):
        app = self.layer['app']
        self.portal = self.layer['portal']
        self.request = self.layer['request']
        self.portal_url = self.portal.absolute_url()
        self.browser = Browser(app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization', 'Basic {0}:{1}'.format(
                SITE_OWNER_NAME,
                SITE_OWNER_PASSWORD,
            ))

    def test_add_news_item(self):
        self.browser.open(self.portal_url)
        self.browser.getLink('News Item').click()
        self.browser.getControl(name='form.widgets.IDublinCore.title')\
            .value = 'My news item'
        self.browser.getControl(name='form.widgets.IDublinCore.description')\
            .value = 'This is my news item.'
        self.browser.getControl(name='form.widgets.IShortName.id')\
            .value = ''
        self.browser.getControl(name='form.widgets.IRichTextBehavior.text')\
            .value = 'Lorem Ipsum'
        self.browser.getControl('Save').click()

        self.assertTrue(self.browser.url.endswith('my-news-item/view'))
        self.assertTrue('My news item' in self.browser.contents)
        self.assertTrue('This is my news item' in self.browser.contents)
        self.assertTrue('Lorem Ipsum' in self.browser.contents)

    def test_add_news_item_with_shortname(self):
        self.browser.open(self.portal_url)
        self.browser.getLink('News Item').click()
        self.browser.getControl(name='form.widgets.IDublinCore.title')\
            .value = 'My news item'
        self.browser.getControl(name='form.widgets.IShortName.id')\
            .value = 'my-special-news'
        self.browser.getControl('Save').click()

        self.assertTrue(self.browser.url.endswith('my-special-news/view'))
Esempio n. 18
0
    def test_local_manager_in_sharing(self):
        transaction.commit()
        browser = Browser(self.layer["app"])
        browser.addHeader(
            "Authorization",
            "Basic %s:%s"
            % (
                TEST_USER_NAME,
                TEST_USER_PASSWORD,
            ),
        )
        browser.open("{}/@@sharing".format(self.entity.absolute_url()))
        content = browser.contents
        self.assertIn("Can manage locally", content)

        browser.open("{}/@@sharing".format(self.contact.absolute_url()))
        content = browser.contents
        self.assertNotIn("Can manage locally", content)
class ControlpanelFunctionalTest(unittest.TestCase):

    layer = PAS_PLUGINS_Authomatic_PLONE_FUNCTIONAL_TESTING

    def setUp(self):
        app = self.layer["app"]
        self.portal = self.layer["portal"]
        self.request = self.layer["request"]
        self.portal_url = self.portal.absolute_url()
        self.browser = Browser(app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            "Authorization",
            f"Basic {SITE_OWNER_NAME}:{SITE_OWNER_PASSWORD}",
        )

    def test_empty_form(self):
        self.browser.open("%s/authomatic-controlpanel" % self.portal_url)
        self.assertTrue(" Settings" in self.browser.contents)
class AllowedFieldsControlPanelFuncionalTest(base.EasyFormTestCase):
    """Test that changes in the easyform control panel are actually
    stored in the registry.
    """
    def setUpPloneSite(self):
        pass

    def setUp(self):
        self.app = self.layer["app"]
        self.portal = self.layer["portal"]
        self.portal_url = self.portal.absolute_url()
        self.browser = Browser(self.app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            "Authorization",
            "Basic " + SITE_OWNER_NAME + ":" + SITE_OWNER_PASSWORD)

    def test_easyform_control_panel_link(self):
        self.browser.open(self.portal_url + "/@@overview-controlpanel")
        self.browser.getLink("easyform").click()
        self.assertTrue("easyform Settings" in self.browser.contents)

    def test_easyform_control_panel_backlink(self):
        self.browser.open(self.portal_url + "/@@easyform-controlpanel")
        self.assertTrue("General" in self.browser.contents)

    def test_easyform_control_panel_sidebar(self):
        self.browser.open(self.portal_url + "/@@navigation-controlpanel")
        self.browser.getLink("Site Setup").click()
        self.assertEqual(self.browser.url,
                         "http://nohost/plone/@@overview-controlpanel")

    def test_easyform_control_panel_checkbox(self):
        self.browser.open(self.portal_url + "/@@easyform-controlpanel")
        self.browser.getControl("Rich Text").selected = False
        self.browser.getControl("Save").click()
        registry = getUtility(IRegistry)
        self.assertNotIn(
            "plone.app.textfield.RichText",
            registry.records["easyform.allowedFields"].value,
        )
Esempio n. 21
0
 def test_sharing(self):
     contact = api.content.create(
         container=self.entity,
         type="imio.directory.Contact",
         title="contact",
     )
     transaction.commit()
     browser = Browser(self.layer["app"])
     browser.handleErrors = False
     browser.addHeader(
         "Authorization",
         "Basic %s:%s" % (
             TEST_USER_NAME,
             TEST_USER_PASSWORD,
         ),
     )
     browser.open("{}/@@sharing".format(contact.absolute_url()))
     checkbox = browser.getControl(name="entries.role_Reader:records")
     checkbox.value = True
     # be sure there is no traceback when sharing (subscriber related)
     browser.getControl(name="form.button.Save").click()
class EventFunctionalTest(unittest.TestCase):

    layer = PLONE_APP_CONTENTTYPES_FUNCTIONAL_TESTING

    def setUp(self):
        app = self.layer['app']
        self.portal = self.layer['portal']
        self.request = self.layer['request']
        self.portal_url = self.portal.absolute_url()
        self.browser = Browser(app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization', 'Basic {0}:{1}'.format(
                SITE_OWNER_NAME,
                SITE_OWNER_PASSWORD,
            ))

    def test_add_event(self):
        self.browser.open(self.portal_url)
        self.browser.getLink('Event').click()
        self.browser.getControl(
            name='form.widgets.IDublinCore.title').value = 'My event'
        self.browser.getControl(name='form.widgets.IDublinCore.description'
                                ).value = 'This is my event.'
        self.browser.getControl(
            name='form.widgets.IRichTextBehavior.text').value = 'Lorem Ipsum'
        self.browser.getControl(
            name='form.widgets.IEventBasic.start').value = '2013-01-01'
        self.browser.getControl(
            name='form.widgets.IEventBasic.end').value = '2013-01-12'
        self.browser.getControl(
            name='form.widgets.IShortName.id').value = 'my-special-event'
        self.browser.getControl('Save').click()

        self.assertTrue(self.browser.url.endswith('my-special-event/view'))
        self.assertIn('My event', self.browser.contents)
        self.assertIn('This is my event', self.browser.contents)
        self.assertIn('Lorem Ipsum', self.browser.contents)
        self.assertIn('2013-01-01', self.browser.contents)
        self.assertIn('2013-01-12', self.browser.contents)
Esempio n. 23
0
class FolderFunctionalTest(unittest.TestCase):

    layer = PLONE_APP_CONTENTTYPES_FUNCTIONAL_TESTING

    def setUp(self):
        app = self.layer['app']
        self.portal = self.layer['portal']
        self.portal_url = self.portal.absolute_url()
        self.browser = Browser(app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization', 'Basic {0}:{1}'.format(
                SITE_OWNER_NAME,
                SITE_OWNER_PASSWORD,
            ))

    def test_add_folder(self):
        self.browser.open(self.portal_url)
        self.browser.getLink(url='http://nohost/plone/++add++Folder').click()
        widget = 'form.widgets.IDublinCore.title'
        self.browser.getControl(name=widget).value = 'My folder'
        widget = 'form.widgets.IShortName.id'
        self.browser.getControl(name=widget).value = ''
        widget = 'form.widgets.IDublinCore.description'
        self.browser.getControl(name=widget).value = 'This is my folder.'
        self.browser.getControl('Save').click()
        self.assertTrue(self.browser.url.endswith('my-folder/view'))
        self.assertTrue('My folder' in self.browser.contents)
        self.assertTrue('This is my folder' in self.browser.contents)

    def test_add_folder_with_shortname(self):
        self.browser.open(self.portal_url)
        self.browser.getLink(url='http://nohost/plone/++add++Folder').click()
        widget = 'form.widgets.IDublinCore.title'
        self.browser.getControl(name=widget).value = 'My folder'
        widget = 'form.widgets.IShortName.id'
        self.browser.getControl(name=widget).value = 'my-special-folder'
        self.browser.getControl('Save').click()
        self.assertTrue(self.browser.url.endswith('my-special-folder/view'))
class EasyFormRegistrationBehaviorFunctionalTest(
    RegistrationFormBase, unittest.TestCase
):
    """ basic use cases and tests for richtext behavior"""

    layer = COLLECTIVE_EASYFORMPLUGIN_REGISTRATION_FUNCTIONAL_TESTING

    _behaviors = ("easyformplugin.registration",)
    _portal_type = "TestEasyForm"

    def setUp(self):
        app = self.layer["app"]
        self.portal = self.layer["portal"]
        self.portal_url = self.portal.absolute_url()
        setRoles(self.portal, TEST_USER_ID, ["Manager"])
        self._setupFTI()
        self.portal.invokeFactory(self._portal_type, "easyform1")
        setRoles(self.portal, TEST_USER_ID, ["Member"])

        import transaction
        transaction.commit()

        # Set up browser
        self.browser = Browser(app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            "Authorization",
            "Basic {0}:{1}".format(
                SITE_OWNER_NAME,
                SITE_OWNER_PASSWORD,
            ),
        )

    def test_easyform_registration_in_edit_form(self):
        self.browser.open(self.portal_url + "/easyform1/edit")
        self.assertTrue("fieldset-registration" in self.browser.contents)

    def test_easyform_registration_behavior(self):
        IRegistrationForm.providedBy(self.portal.easyform1)
class RichTextBehaviorFunctionalTest(RichTextBase, unittest.TestCase):
    """ basic use cases and tests for richtext behavior"""

    layer = PLONE_APP_CONTENTTYPES_FUNCTIONAL_TESTING

    _behaviors = (
        'plone.app.contenttypes.behaviors.richtext.IRichTextBehavior', )
    _portal_type = 'SomeDocument'

    def setUp(self):
        app = self.layer['app']
        self.portal = self.layer['portal']
        self.wf = getToolByName(self.portal, 'portal_workflow')
        self.portal.acl_users._doAddUser('user_std', 'secret', ['Member'], [])
        self.portal_url = self.portal.absolute_url()
        setRoles(self.portal, TEST_USER_ID, ['Manager'])
        self._setupFTI()
        self.portal.invokeFactory(self._portal_type, 'doc1')
        setRoles(self.portal, TEST_USER_ID, ['Member'])
        import transaction
        transaction.commit()
        # Set up browser
        self.browser = Browser(app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization', 'Basic {0}:{1}'.format(
                SITE_OWNER_NAME,
                SITE_OWNER_PASSWORD,
            ))

    def test_richtext_in_edit_form(self):
        self.browser.open(self.portal_url + '/doc1/edit')
        self.assertTrue('tinymce' in self.browser.contents)

    def test_richtext_behavior(self):
        IRichText.providedBy(self.portal.doc1)
Esempio n. 26
0
class LanguageControlPanelFunctionalTest(unittest.TestCase):
    """Test that changes in the language control panel are actually
    stored in the registry.
    """

    layer = PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING

    def setUp(self):
        self.app = self.layer['app']
        self.portal = self.layer['portal']
        self.portal_url = self.portal.absolute_url()
        self.browser = Browser(self.app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization', 'Basic %s:%s' % (
                SITE_OWNER_NAME,
                SITE_OWNER_PASSWORD,
            ))

    def _inject_available_languages_field(self, value):
        """The in-and-out widget does not work without javascript, therefore
           we have to inject some values in order to make saving the form work.
        """
        form = self.browser.getForm(id='LanguageControlPanel')
        name = 'form.widgets.available_languages:list'
        field = webtest.forms.Hidden(form._form, 'input', name, 0, value=value)
        form._form.field_order.append((name, field))
        self.browser.getControl('Save').click()

    def test_language_control_panel_link(self):
        self.browser.open("%s/@@overview-controlpanel" % self.portal_url)
        self.browser.getLink('Language').click()
        self.assertTrue("Language Settings" in self.browser.contents)

    def test_language_control_panel_backlink(self):
        self.browser.open("%s/@@language-controlpanel" % self.portal_url)
        self.assertTrue("General" in self.browser.contents)

    def test_language_control_panel_sidebar(self):
        self.browser.open("%s/@@language-controlpanel" % self.portal_url)
        self.browser.getLink('Site Setup').click()
        self.assertTrue(
            self.browser.url.endswith('/plone/@@overview-controlpanel'))

    def test_language_controlpanel_view(self):
        view = getMultiAdapter((self.portal, self.portal.REQUEST),
                               name="language-controlpanel")
        self.assertTrue(view())

    def test_default_language(self):
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ILanguageSchema, prefix='plone')
        self.browser.open("%s/@@language-controlpanel" % self.portal_url)
        self.assertEqual(settings.default_language, 'en')
        self.assertEqual(
            self.browser.getControl('Site language').value, ['en'])
        self.browser.getControl('Site language').value = ['de']
        self._inject_available_languages_field('en')
        self._inject_available_languages_field('de')
        self.browser.getControl(name='form.buttons.save').click()

        self.assertEqual(settings.default_language, 'de')

    # def test_available_languages(self):
    #     registry = getUtility(IRegistry)
    #     settings = registry.forInterface(ILanguageSchema, prefix='plone')
    #     self.browser.open(
    #         "%s/@@language-controlpanel" % self.portal_url)
    #     self.assertEqual(settings.available_languages, ['en'])
    #     self.assertEqual(
    #         self.browser.getControl(
    #             name='form.widgets.available_languages.to'
    #         ).options,
    #         ['en']
    #     )
    #     control = self.browser.getForm(index=1)
    #     self.in_out_select(
    #         control, 'form.widgets.available_languages:list', 'Deutsch')
    #     self.browser.getControl('Save').click()
    #     self.assertEqual(settings.available_languages, ['en', 'de'])

    def test_use_combined_language_codes(self):
        """This checks swithing combined languages codes support off/on."""
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ILanguageSchema, prefix='plone')
        self.browser.open("%s/@@language-controlpanel" % self.portal_url)
        self.assertEqual(settings.use_combined_language_codes, True)
        self.assertEqual(
            self.browser.getControl(
                'Show country-specific language variants').selected, True)
        self.browser.getControl(
            'Show country-specific language variants').selected = False

        self._inject_available_languages_field('en')
        self.browser.getControl('Save').click()

        self.assertEqual(settings.use_combined_language_codes, False)

    def test_display_flags(self):
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ILanguageSchema, prefix='plone')
        self.browser.open("%s/@@language-controlpanel" % self.portal_url)
        self.assertEqual(settings.display_flags, False)
        self.assertEqual(
            self.browser.getControl('Show language flags').selected, False)
        self.browser.getControl('Show language flags').selected = True

        self._inject_available_languages_field('en')
        self.browser.getControl('Save').click()

        self.assertEqual(settings.display_flags, True)

    def test_use_content_negotiation(self):
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ILanguageSchema, prefix='plone')
        self.browser.open("%s/@@language-controlpanel" % self.portal_url)
        self.assertEqual(settings.use_content_negotiation, False)
        self.assertEqual(
            self.browser.getControl(
                'Use the language of the content item').selected, False)
        self.browser.getControl(
            'Use the language of the content item').selected = True

        self._inject_available_languages_field('en')
        self.browser.getControl('Save').click()

        self.assertEqual(settings.use_content_negotiation, True)

    def test_use_path_negotiation(self):
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ILanguageSchema, prefix='plone')
        self.browser.open("%s/@@language-controlpanel" % self.portal_url)
        self.assertEqual(settings.use_path_negotiation, False)
        self.assertEqual(
            self.browser.getControl(
                'Use language codes in URL path for manual override').selected,
            False)
        self.browser.getControl(
            'Use language codes in URL path for manual override'
        ).selected = True

        self._inject_available_languages_field('en')
        self.browser.getControl('Save').click()

        self.assertEqual(settings.use_path_negotiation, True)

    def test_use_cookie_negotiation(self):
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ILanguageSchema, prefix='plone')
        self.browser.open("%s/@@language-controlpanel" % self.portal_url)
        self.assertEqual(settings.use_cookie_negotiation, False)
        self.assertEqual(
            self.browser.getControl('Use cookie for manual override').selected,
            False)
        self.browser.getControl(
            'Use cookie for manual override').selected = True

        self._inject_available_languages_field('en')
        self.browser.getControl('Save').click()

        self.assertEqual(settings.use_cookie_negotiation, True)

    def test_authenticated_users_only(self):
        control_label = "Authenticated users only"
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ILanguageSchema, prefix='plone')
        self.browser.open("%s/@@language-controlpanel" % self.portal_url)
        self.assertEqual(settings.authenticated_users_only, False)
        self.assertEqual(
            self.browser.getControl(control_label).selected, False)
        self.browser.getControl(control_label).selected = True

        self._inject_available_languages_field('en')
        self.browser.getControl('Save').click()

        self.assertEqual(settings.authenticated_users_only, True)

    def test_set_cookie_always(self):
        control_label = "Set the language cookie always"
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ILanguageSchema, prefix='plone')
        self.browser.open("%s/@@language-controlpanel" % self.portal_url)
        self.assertEqual(settings.set_cookie_always, False)
        self.assertEqual(
            self.browser.getControl(control_label).selected, False)
        self.browser.getControl(control_label).selected = True
        self._inject_available_languages_field('en')
        self.browser.getControl('Save').click()

        self.assertEqual(settings.set_cookie_always, True)

    def test_use_subdomain_negotiation(self):
        control_label = "Use subdomain"
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ILanguageSchema, prefix='plone')
        self.browser.open("%s/@@language-controlpanel" % self.portal_url)
        self.assertEqual(settings.use_subdomain_negotiation, False)
        self.assertEqual(
            self.browser.getControl(control_label).selected, False)
        self.browser.getControl(control_label).selected = True
        self._inject_available_languages_field('en')
        self.browser.getControl('Save').click()

        self.assertEqual(settings.use_subdomain_negotiation, True)

    def test_use_cctld_negotiation(self):
        control_label = "Use top-level domain"
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ILanguageSchema, prefix='plone')
        self.browser.open("%s/@@language-controlpanel" % self.portal_url)
        self.assertEqual(settings.use_cctld_negotiation, False)
        self.assertEqual(
            self.browser.getControl(control_label).selected, False)
        self.browser.getControl(control_label).selected = True
        self._inject_available_languages_field('en')
        self.browser.getControl('Save').click()

        self.assertEqual(settings.use_cctld_negotiation, True)

    def test_use_request_negotiation(self):
        control_label = "Use browser language request negotiation"
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ILanguageSchema, prefix='plone')
        self.browser.open("%s/@@language-controlpanel" % self.portal_url)
        self.assertEqual(settings.use_request_negotiation, False)
        self.assertEqual(
            self.browser.getControl(control_label).selected, False)
        self.browser.getControl(control_label).selected = True
        self._inject_available_languages_field('en')
        self.browser.getControl('Save').click()

        self.assertEqual(settings.use_request_negotiation, True)
Esempio n. 27
0
class FolderViewFunctionalTest(unittest.TestCase):

    layer = PLONE_APP_CONTENTTYPES_FUNCTIONAL_TESTING

    def setUp(self):
        app = self.layer['app']
        self.portal = self.layer['portal']
        self.request = self.layer['request']
        setRoles(self.portal, TEST_USER_ID, ['Manager'])
        self.portal_url = self.portal.absolute_url()
        self.portal.invokeFactory('Folder', id='folder', title='My Folder')
        self.folder = self.portal.folder
        self.folder_url = self.folder.absolute_url()
        self.folder.invokeFactory('Document', id='doc1', title='Document 1')
        import transaction
        transaction.commit()
        self.browser = Browser(app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization', 'Basic {0}:{1}'.format(
                SITE_OWNER_NAME,
                SITE_OWNER_PASSWORD,
            ))

    def test_folder_view(self):
        self.browser.open(self.folder_url + '/view')
        self.assertIn('My Folder', self.browser.contents)
        self.assertIn('Document 1', self.browser.contents)

    def test_folder_summary_view(self):
        self.browser.open(self.folder_url + '/summary_view')
        self.assertIn('My Folder', self.browser.contents)
        self.assertIn('Document 1', self.browser.contents)

    def test_folder_full_view(self):
        self.browser.open(self.folder_url + '/full_view')
        self.assertIn('My Folder', self.browser.contents)
        self.assertIn('Document 1', self.browser.contents)

    def test_folder_tabular_view(self):
        self.browser.open(self.folder_url + '/tabular_view')
        self.assertIn('My Folder', self.browser.contents)
        self.assertIn('Document 1', self.browser.contents)

    def test_folder_album_view(self):
        self.folder.invokeFactory('Image', id='image1', title='Image 1')
        img1 = self.folder['image1']
        img1.image = dummy_image()
        import transaction
        transaction.commit()
        self.browser.open(self.folder_url + '/album_view')
        self.assertIn('My Folder', self.browser.contents)
        self.assertIn('<img src="http://nohost/plone/folder/image1/@@images',
                      self.browser.contents)

    def test_list_item_wout_title(self):
        """In content listings, if a content object has no title use it's id.
        """
        self.folder.invokeFactory('Document', id='doc_wout_title')
        import transaction
        transaction.commit()

        # Document should be shown in listing view (and it's siblings)
        self.browser.open(self.folder_url + "/listing_view")
        self.assertIn('doc_wout_title', self.browser.contents)

        # And also in tabular view
        self.browser.open(self.folder_url + "/tabular_view")
        self.assertIn('doc_wout_title', self.browser.contents)
class UserGroupsControlPanelFunctionalTest(unittest.TestCase):
    """Test that changes in the user groups control panel are actually
    creating and changing users and groups.
    """

    layer = PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING

    def _generateGroups(self):
        groupsTool = getToolByName(self.portal, 'portal_groups')
        self.groups = [
            {'id': 'group1', 'title': "Group 1"},
            {'id': 'group2', 'title': "Group 2"},
            {'id': 'group3', 'title': "Group 3 accentué"}
        ]
        for group in self.groups:
            groupsTool.addGroup(group['id'], [], [], title=group['title'])

    def _generateUsers(self):
        self.members = [
            {'username': '******', 'fullname': 'Kevin Hughes',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Richard Ramirez',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Kyle Brown',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Julian Green',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Makayla Coleman',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Sean Foster',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Molly Martin',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Jordan Thompson',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Tyler Rivera',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Megan Murphy',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Gracie Diaz',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Rachel Morgan',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Maya Price',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Blake Jenkins',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Owen Ramirez',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Owen Cook',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Jayden Hill',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Joseph Ramirez',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Nathan Young',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Kaitlyn Hernandez',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Faith Price',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Sofia Williams',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'David Sanders',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Jack Simmons',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Cole Howard',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Rachel Miller',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Henry Patterson',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Avery Cooper',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Sydney Bennett',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Daniel Johnson',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Autumn Brooks',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Alexandra Nelson',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Brian Simmons',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Kevin Hughes',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Sydney Evans',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Emma Brown',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Lauren Martin',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Isabelle Russell',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Anna Baker',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Brady Watson',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Kaitlyn Robinson',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Riley Richardson',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Kayla Sanders',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Sara Richardson',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Trinity Gonzales',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Madeline Garcia',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Brian Gray',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Victoria Perez',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Charles Rodriguez',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Abigail Simmons',
                'email': '*****@*****.**'},
            {'username': '******', 'fullname': 'Émilie Richard',
                'email': '*****@*****.**'},
        ]
        rtool = getToolByName(self.portal, 'portal_registration')
        for member in self.members:
            rtool.addMember(member['username'],
                            'somepassword', properties=member)

    def setUp(self):
        self.app = self.layer['app']
        self.portal = self.layer['portal']
        self.portal_url = self.portal.absolute_url()
        self.usergroups_url = "%s/@@usergroup-userprefs" % self.portal_url
        self.groups_url = "%s/@@usergroup-groupprefs" % self.portal_url
        self._generateGroups()
        self._generateUsers()
        transaction.commit()

        self.browser = Browser(self.app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization',
            'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)
        )

    def test_usergroups_control_panel_link(self):
        self.browser.open(
            "%s/@@overview-controlpanel" % self.portal_url)
        self.browser.getLink('Users and Groups').click()
        self.assertEqual(
            self.browser.url,
            self.usergroups_url
        )

    def test_usergroups_groups_link(self):
        self.browser.open(self.usergroups_url)
        self.browser.getLink('Groups', index=0).click()
        self.assertEqual(
            self.browser.url,
            "%s/@@usergroup-groupprefs" % self.portal_url
        )

    def test_usergroups_settings_link(self):
        self.browser.open(self.usergroups_url)
        self.browser.getLink('Settings').click()
        self.assertEqual(
            self.browser.url,
            "%s/@@usergroup-controlpanel" % self.portal_url
        )

    def test_usergroups_memberfields_link(self):
        self.browser.open(self.usergroups_url)
        self.browser.getLink('Member fields').click()
        self.assertEqual(
            self.browser.url,
            "%s/@@member-fields" % self.portal_url
        )

    def test_user_search_by_name(self):
        self.browser.open(self.usergroups_url)
        self.browser.getControl(name='searchstring').value = 'Richard'
        self.browser.getControl(name='form.button.Search').click()
        self.assertIn('Richard Ramirez', self.browser.contents)
        self.assertIn('Sara Richardson', self.browser.contents)
        self.assertIn('Émilie Richard', self.browser.contents)

    def test_user_search_by_name_accent(self):
        self.browser.open(self.usergroups_url)
        self.browser.getControl(name='searchstring').value = 'Émilie'
        self.browser.getControl(name='form.button.Search').click()
        self.assertIn('Émilie Richard', self.browser.contents)

    def test_user_search_by_id(self):
        self.browser.open(self.usergroups_url)
        self.browser.getControl(name='searchstring').value = 'TWrMCLIo'
        self.browser.getControl(name='form.button.Search').click()
        self.assertIn('Autumn Brooks', self.browser.contents)

    def test_user_search_by_mail(self):
        self.browser.open(self.usergroups_url)
        self.browser.getControl(name='searchstring').value = 'DohPmgIa@'
        self.browser.getControl(name='form.button.Search').click()
        self.assertIn('Gracie Diaz', self.browser.contents)

    def test_user_show_all(self):
        self.browser.open(self.usergroups_url)
        self.browser.getControl(name='form.button.FindAll').click()

        # Check that first 10 members (sorted by fullname) are shown.
        for member in sorted(
            self.members, key=lambda k: normalizeString(k['fullname'])
        )[:10]:
            self.assertIn(member['fullname'], self.browser.contents)

    def test_user_show_all_with_search_term(self):
        self.browser.open(self.usergroups_url)
        self.browser.getControl(name='searchstring').value = 'no-user'
        self.browser.getControl(name='form.button.FindAll').click()

        # Check that all members is shown and search term is ignored
        self.assertIn('Avery Cooper', self.browser.contents)

    def test_user_add_new_link(self):
        self.browser.open(self.usergroups_url)
        self.browser.getLink(id='add-user').click()
        self.assertEqual(
            self.browser.url,
            "%s/@@new-user" % self.portal_url
        )

    def test_user_modify_roles(self):
        self.browser.open(self.usergroups_url)
        self.browser.getControl(name='searchstring').value = 'TWrMCLIo'
        self.browser.getControl(name='form.button.Search').click()

        # Check that contributor role is not enabled and enable it
        self.assertFalse(self.browser.getControl(
            name='users.roles:list:records'
        ).getControl(value='Contributor').selected)
        self.browser.getControl(
            name='users.roles:list:records'
        ).getControl(value='Contributor').selected = True
        self.browser.getControl(name='form.button.Modify').click()

        # Check that contributor role is now enabled for this user
        self.browser.open(self.usergroups_url)
        self.browser.getControl(name='searchstring').value = 'TWrMCLIo'
        self.browser.getControl(name='form.button.Search').click()
        self.assertTrue(self.browser.getControl(
            name='users.roles:list:records'
        ).getControl(value='Contributor').selected)

    def test_user_delete(self):
        self.browser.open(self.usergroups_url)
        self.browser.getControl(name='searchstring').value = 'TWrMCLIo'
        self.browser.getControl(name='form.button.Search').click()
        self.assertIn('Autumn Brooks', self.browser.contents)

        # Delete user
        self.browser.getControl(name='delete:list').getControl(
            value='TWrMCLIo').selected = True
        self.browser.getControl(name='form.button.Modify').click()

        # Check that user does not exist anymore
        self.browser.getControl(name='searchstring').value = 'TWrMCLIo'
        self.browser.getControl(name='form.button.Search').click()
        self.assertNotIn('Autumn Brooks', self.browser.contents)

    def test_groups_search_by_id(self):
        self.browser.open(self.groups_url)
        self.browser.getControl(name='searchstring').value = 'group1'
        self.browser.getControl(name='form.button.Search').click()
        self.assertIn('Group 1', self.browser.contents)

    def test_groups_search_by_name(self):
        self.browser.open(self.groups_url)
        self.browser.getControl(name='searchstring').value = 'Group 3 accentué'
        self.browser.getControl(name='form.button.Search').click()
        self.assertIn('Group 3 accentué', self.browser.contents)

    def test_groups_modify_roles(self):
        self.browser.open(self.groups_url)
        self.browser.getControl(name='searchstring').value = 'group1'

        # Check that role is not selected yet and then select it and apply it.
        form = self.browser.getForm(id='groups_search')
        ctrls = form._form.fields.get('group_group1:list')
        roles = [ctrl._value for ctrl in ctrls]
        expected = 'Site Administrator'
        self.assertIn(expected, roles)
        idx = roles.index(expected)
        self.assertFalse(ctrls[idx].checked)
        ctrls[idx].checked = True
        self.browser.getControl('Save').click()

        # Check that role is now selected
        form = self.browser.getForm(id='groups_search')
        ctrl = form._form.get('group_group1:list', index=idx)
        self.assertEqual(ctrl._value, expected)
        self.assertTrue(ctrl.checked)

    def test_groups_delete_group(self):
        self.browser.open(self.groups_url)
        self.browser.getControl(name='searchstring').value = 'group1'

        # Delete a group
        self.browser.getControl(
            name='delete:list'
        ).getControl(value='group1').selected = True
        self.browser.getControl(name='form.button.Modify').click()

        # Check that group doesn't exist anymore
        self.browser.getControl(name='searchstring').value = 'group1'
        self.assertNotIn('Group 1', self.browser.contents)

    def test_groups_show_all(self):
        self.browser.open(self.groups_url)
        self.browser.getControl(name='form.button.FindAll').click()

        for group in self.groups:
            self.assertIn(group['title'], self.browser.contents)

    def test_group_add_users(self):
        self.browser.open(self.groups_url)
        self.browser.getLink('Group 1 (group1)').click()
        self.assertIn(
            'There is no group or user attached to this group.',
            self.browser.contents
        )

        # Add user (Autumn Brooks) to selected group (Group 1)
        self.browser.getControl(name='searchstring').value = 'TWrMCLIo'
        self.browser.getControl(name='form.button.Search').click()
        self.browser.getControl(name='add:list').getControl(
            value='TWrMCLIo').selected = True

        # Check that user is now part of the group
        self.browser.getControl(
            'Add selected groups and users to this group').click()
        self.assertIn('Autumn Brooks', self.browser.contents)

    def test_group_add_group(self):
        self.browser.open(self.groups_url)
        self.browser.getLink('Group 1 (group1)').click()
        self.assertIn(
            'There is no group or user attached to this group.',
            self.browser.contents
        )

        # Add group2 to selected  group 1
        self.browser.getControl(name='searchstring').value = 'group2'
        self.browser.getControl(name='form.button.Search').click()
        self.browser.getControl(name='add:list').getControl(
            value='group2').selected = True

        # Check that group is now part of the group
        self.browser.getControl(
            'Add selected groups and users to this group').click()
        self.assertIn('Group 2', self.browser.contents)

    def test_usergroups_settings_many_users(self):
        self.browser.open("%s/@@usergroup-controlpanel" % self.portal_url)
        self.browser.getControl(
            name='form.widgets.many_users:list'
        ).controls[0].selected = True
        self.browser.getControl('Save').click()

        # Check that show all button for users is no longer available
        self.browser.open(self.usergroups_url)
        self.assertNotIn('Show all', self.browser.contents)

        # Check that empty search does not trigger show all
        self.browser.open(self.usergroups_url)
        self.browser.getControl(name='searchstring').value = ''

    def test_usergroups_settings_many_groups(self):
        self.browser.open("%s/@@usergroup-controlpanel" % self.portal_url)
        self.browser.getControl(
            name='form.widgets.many_groups:list'
        ).controls[0].selected = True
        self.browser.getControl('Save').click()

        # Check that show all button for groups is no longer available
        self.browser.open(self.groups_url)
        self.assertNotIn('Show all', self.browser.contents)
        self.assertNotIn('DIispfuF', self.browser.contents)
class RedirectionControlPanelFunctionalTest(unittest.TestCase):
    """Test that changes in the redirection control panel are actually
    stored in the registry.
    """

    layer = PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING

    def setUp(self):
        self.app = self.layer['app']
        self.portal = self.layer['portal']
        self.portal_url = self.portal.absolute_url()
        self.browser = Browser(self.app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization',
            f'Basic {SITE_OWNER_NAME}:{SITE_OWNER_PASSWORD}',
        )

    def test_redirection_controlpanel_link(self):
        self.browser.open("%s/@@overview-controlpanel" % self.portal_url)
        self.browser.getLink('URL Management').click()

    def test_redirection_controlpanel_backlink(self):
        self.browser.open("%s/@@redirection-controlpanel" % self.portal_url)
        self.assertTrue("General" in self.browser.contents)

    def test_redirection_controlpanel_sidebar(self):
        self.browser.open("%s/@@redirection-controlpanel" % self.portal_url)
        self.browser.getLink('Site Setup').click()
        self.assertTrue(
            self.browser.url.endswith('/plone/@@overview-controlpanel')
        )

    def test_redirection_controlpanel_view(self):
        view = getMultiAdapter(
            (self.portal, self.portal.REQUEST), name="redirection-controlpanel"
        )
        self.assertTrue(view())

    def test_redirection_controlpanel_add_redirect(self):
        storage = getUtility(IRedirectionStorage)
        redirection_path = '/alias-folder'
        target_path = '/test-folder'
        storage_path = '/plone/alias-folder'

        self.browser.open("%s/@@redirection-controlpanel" % self.portal_url)
        self.browser.getControl(name='redirection').value = redirection_path
        self.browser.getControl(name='target_path').value = target_path
        self.browser.getControl(name='form.button.Add').click()

        self.assertTrue(
            storage.has_path(storage_path),
            f'Redirection storage should have path "{storage_path}"',
        )

    def test_redirection_controlpanel_remove_redirects(self):
        storage = getUtility(IRedirectionStorage)
        for i in range(31):
            storage[f'/plone/alias{i}'] = '/plone/test-folder'
        transaction.commit()

        self.browser.open("%s/@@redirection-controlpanel" % self.portal_url)
        # A batch of 15 is shown, so some are missing.
        self.assertTrue('/plone/alias1' in self.browser.contents)
        self.assertTrue('/plone/alias10' in self.browser.contents)
        self.assertTrue('/plone/alias19' in self.browser.contents)
        self.assertTrue('/plone/alias2' in self.browser.contents)
        self.assertFalse('/plone/alias29' in self.browser.contents)
        # query aliases starting with /alias2
        self.browser.getControl(name='q').value = '/alias2'
        self.browser.getControl(name='form.button.filter').click()
        self.assertFalse('/plone/alias1' in self.browser.contents)
        self.assertTrue('/plone/alias2' in self.browser.contents)
        self.assertTrue('/plone/alias29' in self.browser.contents)
        # The filter could return one value too much.
        # This tests that we have excludemax=True in the RedirectionSet.
        self.assertFalse('/plone/alias3' in self.browser.contents)
        self.assertFalse('/plone/alias30' in self.browser.contents)
        # Remove two.
        self.browser.getControl(name='redirects:tuple').value = [
            '/plone/alias2',
            '/plone/alias20',
        ]
        self.browser.getControl(name='form.button.Remove').click()
        self.assertFalse('/plone/alias2' in storage)
        self.assertFalse('/plone/alias20' in storage)
        self.assertTrue('/plone/alias1' in storage)
        self.assertTrue('/plone/alias29' in storage)
        self.assertEqual(storage.get('/plone/alias29'), '/plone/test-folder')

    def test_redirection_controlpanel_remove_matching_redirects(self):
        storage = getUtility(IRedirectionStorage)
        for i in range(30):
            storage[f'/plone/alias{i}'] = '/plone/test-folder'
        transaction.commit()

        # Removing matching redirects can only happen when a filter is selected.
        self.browser.open("%s/@@redirection-controlpanel" % self.portal_url)
        self.browser.getControl(name='form.button.MatchRemove').click()
        self.assertTrue(
            'No alternative urls selected for removal.'
            in self.browser.contents
        )
        self.assertEqual(len(storage), 30)
        # query aliases starting with /alias2
        self.browser.getControl(name='q').value = '/alias2'
        # The filter is immediately taken into account,
        # without first explicitly clicking filter.
        # self.browser.getControl(name='form.button.filter').click()
        self.browser.getControl(name='form.button.MatchRemove').click()
        self.assertEqual(len(storage), 19)
        self.assertFalse('/plone/alias2' in storage)
        self.assertFalse('/plone/alias20' in storage)
        self.assertFalse('/plone/alias29' in storage)
        self.assertTrue('/plone/alias1' in storage)
        self.assertTrue('/plone/alias12' in storage)

    def test_redirection_controlpanel_set(self):
        storage = getUtility(IRedirectionStorage)
        portal_path = self.layer['portal'].absolute_url_path()
        now = DateTime('2022-02-03')
        for i in range(1000):
            storage.add(
                '{:s}/foo/{:s}'.format(portal_path, str(i)),
                '{:s}/bar/{:s}'.format(portal_path, str(i)),
                now=now,
            )
        redirects = RedirectionSet()
        self.assertEqual(len(redirects), 1000)
        self.assertDictEqual(
            redirects[0],
            {
                'datetime': DateTime('2022-02-03'),
                'manual': False,
                'path': '/foo/0',
                'redirect': f'{portal_path:s}/foo/0',
                'redirect-to': '/bar/0',
            },
        )
        self.assertDictEqual(
            redirects[999],
            {
                'datetime': DateTime('2022-02-03'),
                'manual': False,
                'path': '/foo/999',
                'redirect': f'{portal_path:s}/foo/999',
                'redirect-to': '/bar/999',
            },
        )
        self.assertEqual(len(list(iter(redirects))), 1000)
        self.assertDictEqual(
            list(iter(redirects))[0],
            {
                'datetime': DateTime('2022-02-03'),
                'manual': False,
                'path': '/foo/0',
                'redirect': f'{portal_path:s}/foo/0',
                'redirect-to': '/bar/0',
            },
        )

    def test_redirection_controlpanel_batching(self):
        storage = getUtility(IRedirectionStorage)
        portal_path = self.layer['portal'].absolute_url_path()
        for i in range(1000):
            storage.add(
                '{:s}/foo/{:s}'.format(portal_path, str(i)),
                '{:s}/bar/{:s}'.format(portal_path, str(i)),
            )
        view = getMultiAdapter(
            (self.layer['portal'], self.layer['request']),
            name='redirection-controlpanel',
        )
        # Test that view/redirects returns batch
        self.assertIsInstance(view.redirects(), Batch)

        # Test that view/batching returns batching with anchor in urls
        batching = view.batching()
        self.assertIn('?b_start:int=990#manage-existing-aliases', batching)

    def test_redirection_controlpanel_redirect_alias_exists(self):
        path_alias = '/alias'
        path_target = '/test-folder'
        storage_alias = f'/plone{path_alias}'
        storage_target = f'/plone{path_target}'
        storage = getUtility(IRedirectionStorage)
        storage.add(storage_alias, storage_target)
        transaction.commit()

        self.browser.open("%s/@@redirection-controlpanel" % self.portal_url)
        self.browser.getControl(name='redirection').value = path_alias
        self.browser.getControl(name='target_path').value = path_target
        self.browser.getControl(name='form.button.Add').click()

        self.assertTrue(
            storage.get(storage_alias) == storage_target,
            f'{storage_target} not target of alternative url!',
        )
        self.assertTrue(
            'The provided alternative url already exists!'
            in self.browser.contents,
            'Message "alternative url already exists" not in page!',
        )

    def test_redirection_controlpanel_filtering(self):
        storage = getUtility(IRedirectionStorage)
        portal_path = self.layer['portal'].absolute_url_path()
        for i in range(1000):
            storage.add(
                '{:s}/foo1/{:s}'.format(portal_path, str(i)),
                '{:s}/bar/{:s}'.format(portal_path, str(i)),
            )
        for i in range(1000):
            storage.add(
                '{:s}/foo2/{:s}'.format(portal_path, str(i)),
                '{:s}/bar/{:s}'.format(portal_path, str(i)),
            )

        redirects = RedirectionSet()
        self.assertEqual(len(redirects), 2000)
        redirects = RedirectionSet(query='/foo')
        self.assertEqual(len(redirects), 2000)
        redirects = RedirectionSet(query='/foo1')
        self.assertEqual(len(redirects), 1000)
        redirects = RedirectionSet(query='/foo2')
        self.assertEqual(len(redirects), 1000)
        # this should return one and not two (we need excludemax=True)
        redirects = RedirectionSet(query='/foo1/777')
        self.assertEqual(len(redirects), 1)

        request = self.layer['request'].clone()
        request.form['q'] = '/foo'
        view = getMultiAdapter(
            (self.layer['portal'], request), name='redirection-controlpanel'
        )
        self.assertEqual(view.redirects().numpages, math.ceil(2000 / 15.0))

        request = self.layer['request'].clone()
        request.form['q'] = '/foo1'
        view = getMultiAdapter(
            (self.layer['portal'], request), name='redirection-controlpanel'
        )
        self.assertEqual(view.redirects().numpages, math.ceil(1000 / 15.0))

        request = self.layer['request'].clone()
        request.form['q'] = '/foo2'
        view = getMultiAdapter(
            (self.layer['portal'], request), name='redirection-controlpanel'
        )
        self.assertEqual(view.redirects().numpages, math.ceil(1000 / 15.0))

        request = self.layer['request'].clone()
        view = getMultiAdapter(
            (self.layer['portal'], request), name='redirection-controlpanel'
        )
        self.assertEqual(view.redirects().numpages, math.ceil(2000 / 15.0))

        # Filtering without new request does not have effect because memoize
        request.form['q'] = '/foo2'
        self.assertEqual(view.redirects().numpages, math.ceil(2000 / 15.0))

    def test_redirection_controlpanel_filter_manual(self):
        storage = getUtility(IRedirectionStorage)
        portal_path = self.layer['portal'].absolute_url_path()
        for i in range(100):
            storage.add(
                '{:s}/foo/{:s}'.format(portal_path, str(i)),
                '{:s}/bar/{:s}'.format(portal_path, str(i)),
                manual=False,
            )
        for i in range(100, 300):
            storage.add(
                '{:s}/foo/{:s}'.format(portal_path, str(i)),
                '{:s}/bar/{:s}'.format(portal_path, str(i)),
                manual=True,
            )

        redirects = RedirectionSet()
        self.assertEqual(len(redirects), 300)
        # Form has yes, no, or empty string, anything else is ignored
        # (so treated as empty string).
        redirects = RedirectionSet(manual='yes')
        self.assertEqual(len(redirects), 200)
        redirects = RedirectionSet(manual='no')
        self.assertEqual(len(redirects), 100)
        redirects = RedirectionSet(manual='')
        self.assertEqual(len(redirects), 300)
        redirects = RedirectionSet(manual='badvalue')
        self.assertEqual(len(redirects), 300)

        request = self.layer['request'].clone()
        request.form['manual'] = ''
        view = getMultiAdapter(
            (self.layer['portal'], request), name='redirection-controlpanel'
        )
        self.assertEqual(view.redirects().numpages, math.ceil(300 / 15.0))

        request = self.layer['request'].clone()
        request.form['manual'] = 'yes'
        view = getMultiAdapter(
            (self.layer['portal'], request), name='redirection-controlpanel'
        )
        self.assertEqual(view.redirects().numpages, math.ceil(200 / 15.0))

        request = self.layer['request'].clone()
        request.form['manual'] = 'no'
        view = getMultiAdapter(
            (self.layer['portal'], request), name='redirection-controlpanel'
        )
        self.assertEqual(view.redirects().numpages, math.ceil(100 / 15.0))

    def test_redirection_controlpanel_filter_date(self):
        storage = getUtility(IRedirectionStorage)
        portal_path = self.layer['portal'].absolute_url_path()
        time0 = DateTime('2001-01-01')
        for i in range(400):
            storage.add(
                '{:s}/foo/{:s}'.format(portal_path, str(i)),
                '{:s}/bar/{:s}'.format(portal_path, str(i)),
                now=time0 + i,
            )

        redirects = RedirectionSet()
        self.assertEqual(len(redirects), 400)
        # created can be anything that can be parsed by DateTime.
        # Otherwise it is ignored.
        self.assertEqual(len(RedirectionSet(created='2019-01-01')), 400)
        self.assertEqual(len(RedirectionSet(created='1999-01-01')), 0)
        self.assertEqual(len(RedirectionSet(created='2001-01-01')), 0)
        self.assertEqual(len(RedirectionSet(created='2001-01-02')), 1)
        self.assertEqual(len(RedirectionSet(created='2001-02-01')), 31)
        self.assertEqual(len(RedirectionSet(created='2001-02-01 00:00:00')), 31)
        self.assertEqual(len(RedirectionSet(created='2001-02-01 00:00:01')), 32)
        self.assertEqual(len(RedirectionSet(created='badvalue')), 400)

        # DateTime('2002-01-01') results in a timezone GMT+0
        self.assertEqual(len(RedirectionSet(created='2002-01-01')), 365)
        # DateTime('2002/01/01') results in a timezone GMT+1 for me,
        # or a different zone depending on where in the world you are.
        # So we need to be lenient in the tests.
        self.assertGreaterEqual(len(RedirectionSet(created='2002/01/01')), 364)
        self.assertLessEqual(len(RedirectionSet(created='2002/01/01')), 366)

        request = self.layer['request'].clone()
        request.form['datetime'] = ''
        view = getMultiAdapter(
            (self.layer['portal'], request), name='redirection-controlpanel'
        )
        self.assertEqual(view.redirects().numpages, math.ceil(400 / 15.0))

        request = self.layer['request'].clone()
        request.form['datetime'] = '2001-01-27'
        view = getMultiAdapter(
            (self.layer['portal'], request), name='redirection-controlpanel'
        )
        self.assertEqual(view.redirects().numpages, math.ceil(27 / 15.0))

        request = self.layer['request'].clone()
        request.form['datetime'] = '2002-01-01'
        view = getMultiAdapter(
            (self.layer['portal'], request), name='redirection-controlpanel'
        )
        self.assertEqual(view.redirects().numpages, math.ceil(365 / 15.0))

        request = self.layer['request'].clone()
        request.form['datetime'] = '2019-01-01'
        view = getMultiAdapter(
            (self.layer['portal'], request), name='redirection-controlpanel'
        )
        self.assertEqual(view.redirects().numpages, math.ceil(400 / 15.0))

    def test_redirection_controlpanel_redirect_no_target(self):
        path_alias = '/alias'
        path_target = '/not-existing'

        self.browser.open("%s/@@redirection-controlpanel" % self.portal_url)
        self.browser.getControl(name='redirection').value = path_alias
        self.browser.getControl(name='target_path').value = path_target
        self.browser.getControl(name='form.button.Add').click()

        self.assertTrue(
            'The provided target object does not exist.'
            in self.browser.contents,
            'Message "target does not exist" not in page!',
        )

    def test_redirection_controlpanel_missing_slash_target(self):
        path_alias = '/alias'
        path_target = 'Members'

        self.browser.open("%s/@@redirection-controlpanel" % self.portal_url)
        self.browser.getControl(name='redirection').value = path_alias
        self.browser.getControl(name='target_path').value = path_target
        self.browser.getControl(name='form.button.Add').click()

        self.assertTrue(
            'Target path must start with a slash.' in self.browser.contents,
            'Errormessage for missing slash on target path missing',
        )

    def test_redirection_controlpanel_missing_slash_alias(self):
        path_alias = 'alias'
        path_target = '/Members'

        self.browser.open("%s/@@redirection-controlpanel" % self.portal_url)
        self.browser.getControl(name='redirection').value = path_alias
        self.browser.getControl(name='target_path').value = path_target
        self.browser.getControl(name='form.button.Add').click()

        self.assertTrue(
            'Alternative url path must start with a slash.'
            in self.browser.contents,
            'Errormessage for missing slash on alternative url missing',
        )

    def test_manage_aliases_standard(self):
        storage = getUtility(IRedirectionStorage)
        folder = self.portal['test-folder']

        self.browser.open("%s/@@manage-aliases" % folder.absolute_url())
        self.browser.getControl(name='redirection').value = '/alias'
        self.browser.getControl(name='form.button.Add').click()

        self.assertTrue(
            'Alternative url added.' in self.browser.contents,
            'Message for added alternative url missing',
        )
        self.assertTrue(storage.has_path('/plone/alias'))
        self.assertEqual(storage.get('/plone/alias'), '/plone/test-folder')

    def test_manage_aliases_remove(self):
        storage = getUtility(IRedirectionStorage)
        folder = self.portal['test-folder']
        storage['/plone/alias1'] = '/plone/test-folder'
        storage['/plone/alias2'] = '/plone/test-folder'
        storage['/plone/alias3'] = '/plone/test-folder'
        transaction.commit()

        self.browser.open("%s/@@manage-aliases" % folder.absolute_url())
        self.browser.getControl(name='redirects:tuple').value = [
            '/plone/alias1',
            '/plone/alias2',
        ]
        self.browser.getControl(name='form.button.Remove').click()

        self.assertTrue(
            'Alternative urls removed.' in self.browser.contents,
            'Message for removed alternative url missing',
        )
        self.assertFalse('/plone/alias1' in storage)
        self.assertFalse('/plone/alias2' in storage)
        self.assertTrue('/plone/alias3' in storage)
        self.assertEqual(storage.get('/plone/alias3'), '/plone/test-folder')

    def test_manage_aliases_navigation_root(self):
        from zope.interface import alsoProvides
        from plone.app.layout.navigation.interfaces import INavigationRoot

        storage = getUtility(IRedirectionStorage)
        folder = self.portal['test-folder']
        alsoProvides(folder, INavigationRoot)
        transaction.commit()

        self.browser.open("%s/@@manage-aliases" % folder.absolute_url())
        self.browser.getControl(name='redirection').value = '/alias'
        self.browser.getControl(name='form.button.Add').click()

        self.assertTrue(
            'Alternative url added.' in self.browser.contents,
            'Message for added alternative url missing',
        )
        self.assertTrue(storage.has_path('/plone/test-folder/alias'))
        self.assertEqual(
            storage.get('/plone/test-folder/alias'), '/plone/test-folder'
        )

        # Add the navigation root path explicitly.
        self.browser.getControl(
            name='redirection'
        ).value = '/test-folder/alias2'
        self.browser.getControl(name='form.button.Add').click()

        self.assertTrue(
            'Alternative url added.' in self.browser.contents,
            'Message for added alternative url missing',
        )
        self.assertTrue(storage.has_path('/plone/test-folder/alias2'))
        self.assertEqual(
            storage.get('/plone/test-folder/alias2'), '/plone/test-folder'
        )

    def test_absolutize_path(self):
        # absolutize_path is a helper function that returns a tuple
        # of absolute path and error message.
        from Products.CMFPlone.controlpanel.browser.redirects import (
            absolutize_path as ap,
        )

        # A path is required.
        self.assertEqual(ap(''), ('', 'You have to enter an alternative url.'))
        self.assertEqual(
            ap('', is_source=False), ('', 'You have to enter a target.')
        )

        # relative paths are not accepted
        self.assertEqual(
            ap('foo'), ('foo', 'Alternative url path must start with a slash.')
        )
        self.assertEqual(
            ap('foo', is_source=True),
            ('foo', 'Alternative url path must start with a slash.'),
        )
        self.assertEqual(
            ap('foo', is_source=False),
            ('foo', 'Target path must start with a slash.'),
        )

        # absolute paths are good
        self.assertEqual(ap('/foo'), ('/plone/foo', None))
        self.assertEqual(ap('/foo', is_source=True), ('/plone/foo', None))

        # for targets, an object must exist on the path
        self.assertEqual(
            ap('/foo', is_source=False),
            ('/plone/foo', 'The provided target object does not exist.'),
        )
        self.assertEqual(
            ap('/test-folder', is_source=False), ('/plone/test-folder', None)
        )
        self.assertEqual(
            ap('/test-folder/@@sharing', is_source=False),
            ('/test-folder/@@sharing', 'Target path must not be a view.'),
        )

        # A source must not exist.
        self.assertEqual(
            ap('/test-folder'),
            (
                '/plone/test-folder',
                'Cannot use a working path as alternative url.',
            ),
        )
        # More general: a source must not be traversable already.
        self.assertEqual(
            ap('/view'),
            ('/plone/view', 'Cannot use a working path as alternative url.'),
        )
        self.assertEqual(
            ap('/@@overview-controlpanel'),
            (
                '/@@overview-controlpanel',
                'Alternative url path must not be a view.',
            ),
        )

        # And a source must not exist via (implicit) acquisition.
        # We might *want* to allow this, but such a redirect would not have effect,
        # because acquisition happens earlier.
        # See https://github.com/collective/Products.RedirectionTool/issues/12
        self.portal.invokeFactory('Document', 'doc')
        self.assertEqual(
            ap('/test-folder/doc'),
            (
                '/plone/test-folder/doc',
                'Cannot use a working path as alternative url.',
            ),
        )

        # A source must not already exist in the redirect list.
        storage = getUtility(IRedirectionStorage)
        portal_path = self.portal.absolute_url_path()
        storage.add(
            f'{portal_path:s}/foo',
            f'{portal_path:s}/test-folder',
        )
        self.assertEqual(
            ap('/foo', is_source=True),
            ('/plone/foo', 'The provided alternative url already exists!'),
        )

        # For targets, we now accept external urls.
        # Note that this can only be done on the control panel,
        # so by default only by Site Administrators or Managers.
        self.assertEqual(
            ap('https://example.org', is_source=False),
            ('https://example.org', None),
        )
        self.assertEqual(
            ap('http://example.org', is_source=False),
            ('http://example.org', None),
        )
        self.assertEqual(
            ap(
                'https://example.org/some/path?foo=bar&bar=foo',
                is_source=False,
            ),
            ('https://example.org/some/path?foo=bar&bar=foo', None),
        )
        self.assertEqual(
            ap('http://', is_source=False),
            ('http://', 'Target path must start with a slash.'),
        )
        # Using '//' to ignore http/https differences seems useless,
        # as we don't include content but only link to it.
        self.assertEqual(
            ap('//example.org', is_source=False),
            (
                '/plone//example.org',
                'The provided target object does not exist.',
            ),
        )

    def test_upload_two_columns(self):
        self.browser.open("%s/@@redirection-controlpanel" % self.portal_url)
        # Note: the targets must exist as actual content.
        data = [
            (b'/old-home-page.asp', b'/test-folder'),
            (b'/people/JoeT', b'/Members'),
        ]
        csv = b'\n'.join([b','.join(d) for d in data])
        self.browser.getControl(name='file').add_file(
            io.BytesIO(csv), 'text/plain', 'redirects.csv'
        )
        self.browser.getControl(name='form.button.Upload').click()
        self.assertNotIn(
            'Please pick a file to upload.', self.browser.contents
        )
        self.assertNotIn(
            'No alternative urls were added.', self.browser.contents
        )
        self.assertNotIn('Please correct these errors', self.browser.contents)
        storage = getUtility(IRedirectionStorage)
        self.assertEqual(len(storage), 2)
        self.assertEqual(
            storage.get('/plone/old-home-page.asp'), '/plone/test-folder'
        )
        self.assertEqual(storage.get('/plone/people/JoeT'), '/plone/Members')
        # Test the internals.
        redirect = storage._paths['/plone/old-home-page.asp']
        self.assertEqual(redirect[0], '/plone/test-folder')
        self.assertIsInstance(redirect[1], DateTime)
        self.assertEqual(redirect[2], True)  # manual

    def test_upload_four_columns(self):
        # Two columns are the minimum,
        # but we can handle a third column with a datetime,
        # a fourth column with manual True/False,
        # and more columns that we ignore.
        now = DateTime()
        self.browser.open("%s/@@redirection-controlpanel" % self.portal_url)
        # Note: the targets must exist as actual content.
        data = [
            # We can first have a header, which should be ignored.
            # Second one should have the same number of columns,
            # otherwise the delimiter detection can get it wrong.
            (b'old path', b'new path', b'datetime', b'manual'),
            # bad dates are silently ignored
            (b'/baddate', b'/test-folder', b'2006-13-62', b'yes'),
            # two columns:
            (b'/two', b'/test-folder'),
            # third column with date:
            (b'/three', b'/test-folder', b'2003-01-31'),
            # fourth column with manual:
            (
                b'/four',
                b'/test-folder',
                b'2004/01/27 10:00:00 GMT-3',
                b'False',
            ),
            # fifth column is ignored:
            (b'/five', b'/test-folder', b'2005-01-31', b'True', b'ignored'),
            # manual can be '0' (or anything starting with f/F/n/N/0)
            (b'/zero', b'/test-folder', b'2000-01-31', b'0'),
        ]
        csv = b'\n'.join([b','.join(d) for d in data])
        self.browser.getControl(name='file').add_file(
            io.BytesIO(csv), 'text/plain', 'redirects.csv'
        )
        self.browser.getControl(name='form.button.Upload').click()
        self.assertNotIn(
            'Please pick a file to upload.', self.browser.contents
        )
        self.assertNotIn(
            'No alternative urls were added.', self.browser.contents
        )
        self.assertNotIn('Please correct these errors', self.browser.contents)

        # All five lines have been added.
        storage = getUtility(IRedirectionStorage)
        self.assertEqual(len(storage), 6)
        self.assertEqual(storage.get('/plone/two'), '/plone/test-folder')
        old_paths = [
            '/plone/baddate',
            '/plone/five',
            '/plone/four',
            '/plone/three',
            '/plone/two',
            '/plone/zero',
        ]
        self.assertListEqual(sorted(list(storage)), old_paths)
        self.assertListEqual(
            sorted(list(storage.redirects('/plone/test-folder'))), old_paths
        )
        # Test the internals.

        # two columns:
        # (b'/two', b'/test-folder'),
        redirect = storage._paths['/plone/two']
        self.assertEqual(redirect[0], '/plone/test-folder')
        self.assertIsInstance(redirect[1], DateTime)
        self.assertGreater(redirect[1], now)
        self.assertEqual(redirect[2], True)  # manual

        # third column with date:
        # (b'/three', b'/test-folder', b'2003-01-31'),
        redirect = storage._paths['/plone/three']
        self.assertEqual(redirect[0], '/plone/test-folder')
        self.assertEqual(redirect[1], DateTime('2003-01-31'))
        self.assertEqual(redirect[2], True)

        # fourth column with manual:
        # (b'/four', b'/test-folder', b'2004/01/27 10:00:00 GMT-3', b'False'),
        redirect = storage._paths['/plone/four']
        self.assertEqual(redirect[0], '/plone/test-folder')
        self.assertEqual(redirect[1], DateTime('2004/01/27 10:00:00 GMT-3'))
        self.assertEqual(redirect[2], False)

        # fifth column is ignored:
        # (b'/five', b'/test-folder', b'2005-01-31', b'True', b'ignored'),
        redirect = storage._paths['/plone/five']
        self.assertEqual(redirect[0], '/plone/test-folder')
        self.assertEqual(redirect[1], DateTime('2005-01-31'))
        self.assertEqual(redirect[2], True)

        # manual can be '0' (or anything starting with f/F/n/N/0)
        # (b'/zero', b'/test-folder', b'2000-01-31', b'0'),
        redirect = storage._paths['/plone/zero']
        self.assertEqual(redirect[0], '/plone/test-folder')
        self.assertEqual(redirect[1], DateTime('2000-01-31'))
        self.assertEqual(redirect[2], False)

        # bad dates are silently ignored
        # (b'/baddate', b'/test-folder', b'2006-13-62', b'yes'),
        redirect = storage._paths['/plone/baddate']
        self.assertEqual(redirect[0], '/plone/test-folder')
        self.assertGreater(redirect[1], now)
        self.assertEqual(redirect[2], True)

    def test_upload_bad(self):
        self.browser.open("%s/@@redirection-controlpanel" % self.portal_url)
        # The targets must exist as actual content.
        # We try a good one and one that does not exist.
        data = [
            (b'/old-home-page.asp', b'/test-folder'),
            (b'/people/JoeT', b'/no-such-content'),
        ]
        csv = b'\n'.join([b','.join(d) for d in data])
        self.browser.getControl(name='file').add_file(
            io.BytesIO(csv), 'text/plain', 'redirects.csv'
        )
        self.browser.getControl(name='form.button.Upload').click()
        self.assertNotIn(
            'Please pick a file to upload.', self.browser.contents
        )
        self.assertIn('No alternative urls were added.', self.browser.contents)
        self.assertIn('Please correct these errors', self.browser.contents)
        storage = getUtility(IRedirectionStorage)
        self.assertEqual(len(storage), 0)

    def test_download_empty(self):
        self.browser.open("%s/@@redirection-controlpanel" % self.portal_url)
        self.browser.getControl(name='form.button.Download').click()
        self.assertEqual(
            self.browser.headers['Content-Disposition'],
            'attachment; filename=redirects.csv',
        )
        contents = self.browser.contents.splitlines()
        self.assertEqual(len(contents), 1)
        self.assertEqual(contents[0], 'old path,new path,datetime,manual')

    def test_download_bigger(self):
        storage = getUtility(IRedirectionStorage)
        portal_path = self.layer['portal'].absolute_url_path()
        now = DateTime('2019/01/27 10:00:00 GMT-3')
        for i in range(2000):
            storage.add(
                '{:s}/foo/{:s}'.format(portal_path, str(i)),
                '{:s}/bar/{:s}'.format(portal_path, str(i)),
                now=now,
                manual=True,
            )
        transaction.commit()
        self.browser.open("%s/@@redirection-controlpanel" % self.portal_url)
        self.browser.getControl(name='form.button.Download').click()
        self.assertEqual(
            self.browser.headers['Content-Disposition'],
            'attachment; filename=redirects.csv',
        )
        contents = self.browser.contents.splitlines()
        # pop the header
        self.assertEqual(contents.pop(0), 'old path,new path,datetime,manual')
        self.assertEqual(len(contents), 2000)
        # The order is probably the alphabetical order of the old path,
        # but that is not important and may change,
        # so let's sort it in the tests for good measure.
        # Note that '999' sorts alphabetically after '1999'.
        contents.sort()
        self.assertEqual(
            contents[0], '/foo/0,/bar/0,2019/01/27 10:00:00 GMT-3,True'
        )
        self.assertEqual(
            contents[1999], '/foo/999,/bar/999,2019/01/27 10:00:00 GMT-3,True'
        )

    def test_download_upload(self):
        # Test uploading a download and downloading an upload.

        # 1. Manually add some redirects.
        storage = getUtility(IRedirectionStorage)
        portal_path = self.layer['portal'].absolute_url_path()
        now = DateTime('2019/01/27 10:00:00 GMT-3')
        for i in range(10):
            storage.add(
                '{:s}/foo/{:s}'.format(portal_path, str(i)),
                f'{portal_path:s}/test-folder',
                now=now,
                manual=True,
            )
        transaction.commit()

        # 2. Download the redirects.
        self.browser.open("%s/@@redirection-controlpanel" % self.portal_url)
        self.browser.getControl(name='form.button.Download').click()
        self.assertEqual(
            self.browser.headers['Content-Disposition'],
            'attachment; filename=redirects.csv',
        )
        downloaded_contents = self.browser.contents
        contents = downloaded_contents.splitlines()
        self.assertEqual(contents.pop(0), 'old path,new path,datetime,manual')
        self.assertEqual(len(contents), 10)
        contents.sort()
        self.assertEqual(
            contents[0], '/foo/0,/test-folder,2019/01/27 10:00:00 GMT-3,True'
        )

        # 3. clear the redirect storage
        storage.clear()
        transaction.commit()
        self.browser.open("%s/@@redirection-controlpanel" % self.portal_url)
        self.browser.getControl(name='form.button.Download').click()
        contents = self.browser.contents.splitlines()
        self.assertEqual(len(contents), 1)
        self.assertEqual(contents[0], 'old path,new path,datetime,manual')

        # 4. upload the original download
        self.browser.open("%s/@@redirection-controlpanel" % self.portal_url)
        self.browser.getControl(name='file').add_file(
            io.BytesIO(safe_bytes(downloaded_contents)),
            'text/plain',
            'redirects.csv',
        )
        self.browser.getControl(name='form.button.Upload').click()
        self.assertNotIn(
            'Please pick a file to upload.', self.browser.contents
        )
        self.assertNotIn(
            'The provided target object does not exist.', self.browser.contents
        )
        self.assertNotIn(
            'No alternative urls were added.', self.browser.contents
        )
        self.assertNotIn('Please correct these errors', self.browser.contents)
        self.assertEqual(len(storage), 10)

        # 5. download the upload
        self.browser.getControl(name='form.button.Download').click()
        new_downloaded_contents = self.browser.contents
        contents = downloaded_contents.splitlines()
        self.assertEqual(contents.pop(0), 'old path,new path,datetime,manual')
        self.assertEqual(len(contents), 10)
        contents.sort()
        self.assertEqual(
            contents[0], '/foo/0,/test-folder,2019/01/27 10:00:00 GMT-3,True'
        )
        # and it is actually the same as the original download
        self.assertEqual(new_downloaded_contents, downloaded_contents)
class FilterControlPanelFunctionalTest(unittest.TestCase):
    """Test that changes in the site control panel are actually
    stored in the registry.
    """

    layer = PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING

    def setUp(self):
        self.app = self.layer['app']
        self.portal = self.layer['portal']
        self.request = self.layer['request']
        self.portal_url = self.portal.absolute_url()
        registry = getUtility(IRegistry)
        self.settings = registry.forInterface(
            IFilterSchema, prefix="plone")
        self.browser = Browser(self.app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization',
            'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)
        )
        self.safe_html = getattr(
            getToolByName(self.portal, 'portal_transforms'),
            'safe_html',
            None)

    def test_filter_control_panel_link(self):
        self.browser.open(
            "%s/@@overview-controlpanel" % self.portal_url)
        self.browser.getLink('Site').click()

    def test_filter_control_panel_backlink(self):
        self.browser.open(
            "%s/@@filter-controlpanel" % self.portal_url)
        self.assertTrue("Security" in self.browser.contents)

    def test_filter_control_panel_sidebar(self):
        self.browser.open(
            "%s/@@filter-controlpanel" % self.portal_url)
        self.browser.getLink('Site Setup').click()
        self.assertTrue(
            self.browser.url.endswith('/plone/@@overview-controlpanel')
        )

    def test_filter_controlpanel_view(self):
        view = getMultiAdapter((self.portal, self.portal.REQUEST),
                               name="filter-controlpanel")
        self.assertTrue(view())

    def test_disable_filtering(self):
        self.browser.open(
            "%s/@@filter-controlpanel" % self.portal_url)
        self.browser.getControl(
            name='form.widgets.disable_filtering:list').value = "selected"
        self.browser.getControl('Save').click()

        # test that the transform is disabled
        self.assertEqual(
            self.settings.disable_filtering,
            1)

        # anything passes
        nasty_html = '<script></script>'
        ds = datastream('dummy_name')
        self.assertEqual(
            nasty_html,
            str(self.safe_html.convert(nasty_html, ds))
        )

    def test_nasty_tags(self):
        self.browser.open(
            "%s/@@filter-controlpanel" % self.portal_url)
        self.assertEqual(
            self.browser.getControl(name='form.widgets.nasty_tags').value,
            'style\nobject\nembed\napplet\nscript\nmeta')
        self.browser.getControl(
            name='form.widgets.nasty_tags').value = 'div\na'
        valid_tags = self.browser.getControl(
            name='form.widgets.valid_tags').value
        self.assertTrue(valid_tags.startswith('a\nabbr\nacronym\naddress'))
        valid_tags = valid_tags.replace('a\n', '')
        valid_tags = self.browser.getControl(
            name='form.widgets.valid_tags').value = valid_tags
        self.browser.getControl('Save').click()
        self.assertEqual(self.settings.nasty_tags, [u'div', u'a'])
        self.assertNotIn(u'a', self.settings.valid_tags)

        # test that <a> is filtered
        self.assertFalse(self.settings.disable_filtering)
        good_html = '<p><a href="http://example.com">harmless link</a></p>'
        ds = datastream('dummy_name')
        self.assertEqual(
            self.safe_html.convert(good_html, ds).getData(),
            '<p/>'
        )
class SearchControlPanelFunctionalTest(unittest.TestCase):
    """Test that changes in the search control panel are actually
    stored in the registry.
    """

    layer = PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING

    def setUp(self):
        self.app = self.layer['app']
        self.portal = self.layer['portal']
        self.portal_url = self.portal.absolute_url()
        self.browser = Browser(self.app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization',
            'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)
        )

    def test_search_control_panel_link(self):
        self.browser.open(
            "%s/@@overview-controlpanel" % self.portal_url)
        self.browser.getLink('Search').click()

    def test_search_control_panel_backlink(self):
        self.browser.open(
            "%s/@@search-controlpanel" % self.portal_url)
        self.assertTrue("General" in self.browser.contents)

    def test_search_control_panel_sidebar(self):
        self.browser.open(
            "%s/@@search-controlpanel" % self.portal_url)
        self.browser.getLink('Site Setup').click()
        self.assertTrue(
            self.browser.url.endswith('/plone/@@overview-controlpanel')
        )

    def test_search_controlpanel_view(self):
        view = getMultiAdapter((self.portal, self.portal.REQUEST),
                               name="search-controlpanel")
        self.assertTrue(view())

    def test_enable_livesearch(self):
        self.browser.open(
            "%s/@@search-controlpanel" % self.portal_url)
        self.browser.getControl('Enable LiveSearch').selected = True
        self.browser.getControl('Save').click()

        registry = getUtility(IRegistry)
        settings = registry.forInterface(ISearchSchema, prefix="plone")
        self.assertEqual(settings.enable_livesearch, True)

    def test_types_not_searched(self):
        self.browser.open(
            "%s/@@search-controlpanel" % self.portal_url)
        self.browser.getControl(
            name='form.widgets.types_not_searched:list'
        ).value = ['Discussion Item', 'News Item']
        self.browser.getControl('Save').click()

        registry = getUtility(IRegistry)
        settings = registry.forInterface(ISearchSchema, prefix="plone")
        self.assertFalse('Discussion Item' in settings.types_not_searched)
        self.assertFalse('News Item Item' in settings.types_not_searched)
class NavigationControlPanelFunctionalTest(unittest.TestCase):
    """Test that changes in the navigation control panel are actually
    stored in the registry.
    """

    layer = PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING

    def setUp(self):
        self.app = self.layer['app']
        self.portal = self.layer['portal']
        self.portal_url = self.portal.absolute_url()
        self.browser = Browser(self.app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization',
            'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)
        )

    def test_navigation_control_panel_link(self):
        self.browser.open(
            "%s/@@overview-controlpanel" % self.portal_url)
        self.browser.getLink('Navigation').click()
        self.assertTrue("Navigation Settings" in self.browser.contents)

    def test_navigation_control_panel_backlink(self):
        self.browser.open(
            "%s/@@navigation-controlpanel" % self.portal_url)
        self.assertTrue("General" in self.browser.contents)

    def test_navigation_control_panel_sidebar(self):
        self.browser.open(
            "%s/@@navigation-controlpanel" % self.portal_url)
        self.browser.getLink('Site Setup').click()
        self.assertTrue(
            self.browser.url.endswith('/plone/@@overview-controlpanel')
        )

    def test_navigation_controlpanel_view(self):
        view = getMultiAdapter((self.portal, self.portal.REQUEST),
                               name="navigation-controlpanel")
        self.assertTrue(view())

    def test_generate_tabs(self):
        registry = getUtility(IRegistry)
        settings = registry.forInterface(INavigationSchema, prefix='plone')
        self.browser.open(
            "%s/@@navigation-controlpanel" % self.portal_url)
        self.assertEqual(settings.generate_tabs, True)
        self.assertEqual(
            self.browser.getControl('Automatically generate tabs').selected,
            True
        )
        self.browser.getControl('Automatically generate tabs').selected = False
        self.browser.getControl('Save').click()

        self.assertEqual(settings.generate_tabs, False)

    def test_nonfolderish_tabs(self):
        registry = getUtility(IRegistry)
        settings = registry.forInterface(INavigationSchema, prefix='plone')
        self.browser.open(
            "%s/@@navigation-controlpanel" % self.portal_url)
        self.assertEqual(settings.generate_tabs, True)
        self.assertEqual(
            self.browser.getControl('Automatically generate tabs').selected,
            True
        )
        self.browser.getControl(
            'Generate tabs for items other than folders').selected = False
        self.browser.getControl('Save').click()

        self.assertEqual(settings.nonfolderish_tabs, False)

    def test_displayed_types(self):
        registry = getUtility(IRegistry)
        settings = registry.forInterface(INavigationSchema, prefix='plone')
        self.browser.open(
            "%s/@@navigation-controlpanel" % self.portal_url)
        self.browser.getControl('Collection', index=0).selected = True
        self.browser.getControl('Comment').selected = True
        self.browser.getControl('Event').selected = True
        self.browser.getControl('File').selected = True
        self.browser.getControl('Folder').selected = True
        self.browser.getControl('Image').selected = True
        self.browser.getControl('Link').selected = True
        self.browser.getControl('News Item').selected = True
        self.browser.getControl('Page').selected = True
        self.browser.getControl('Save').click()

        self.assertTrue('Collection' in settings.displayed_types)
        self.assertTrue('Discussion Item' in settings.displayed_types)
        self.assertTrue('Event' in settings.displayed_types)
        self.assertTrue('File' in settings.displayed_types)
        self.assertTrue('Folder' in settings.displayed_types)
        self.assertTrue('Image' in settings.displayed_types)
        self.assertTrue('Link' in settings.displayed_types)
        self.assertTrue('News Item' in settings.displayed_types)
        self.assertTrue('Document' in settings.displayed_types)

    def test_workflow_settings(self):
        registry = getUtility(IRegistry)
        settings = registry.forInterface(INavigationSchema, prefix='plone')
        self.browser.open(
            "%s/@@navigation-controlpanel" % self.portal_url)

        self.browser.getControl('Filter on workflow state').selected = True
        self.browser.getControl('Externally visible [external]').selected = True  # noqa
        self.browser.getControl('Internal draft [internal]').selected = True
        self.browser.getControl('Internally published [internally_published]').selected = True  # noqa
        self.browser.getControl('Pending [pending]').selected = True
        self.browser.getControl('Private [private]').selected = True
        self.browser.getControl('Public draft [visible]').selected = True
        self.browser.getControl('Published [published]').selected = True
        self.browser.getControl("Save").click()

        self.assertTrue(self.browser.url.endswith('navigation-controlpanel'))
        self.assertTrue('Changes saved.' in self.browser.contents)

        self.assertTrue(settings.filter_on_workflow)

        self.assertTrue('external' in settings.workflow_states_to_show)
        self.assertTrue('internal' in settings.workflow_states_to_show)
        self.assertTrue('internally_published' in settings.workflow_states_to_show)  # noqa
        self.assertTrue('pending' in settings.workflow_states_to_show)
        self.assertTrue('private' in settings.workflow_states_to_show)
        self.assertTrue('visible' in settings.workflow_states_to_show)
        self.assertTrue('published' in settings.workflow_states_to_show)

    def test_show_excluded_items(self):
        registry = getUtility(IRegistry)
        settings = registry.forInterface(INavigationSchema, prefix='plone')
        self.browser.open(
            "%s/@@navigation-controlpanel" % self.portal_url)

        self.browser.getControl(
            'Show items normally excluded from navigation if viewing their children.').selected = False  # noqa
        self.browser.getControl("Save").click()

        self.assertFalse(settings.show_excluded_items)
class TypesControlPanelFunctionalTest(unittest.TestCase):
    """Test that changes in the types control panel are actually
    stored in the registry.
    """

    layer = PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING

    def setUp(self):
        self.app = self.layer['app']
        self.portal = self.layer['portal']
        self.portal_url = self.portal.absolute_url()
        self.types_url = "%s/@@content-controlpanel" % self.portal_url
        self.browser = Browser(self.app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization',
            'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)
        )

    def test_types_control_panel_link(self):
        self.browser.open(
            "%s/@@overview-controlpanel" % self.portal_url)
        self.browser.getLink('Editing').click()

    def test_standard_type_select(self):
        self.browser.open(self.types_url)
        self.browser.getControl(name='type_id').value = ['Link']
        self.browser.getForm(action=self.types_url).submit()
        self.assertIn('content-controlpanel', self.browser.url)

    def test_standard_type_cancel(self):
        self.browser.open(self.types_url)
        self.browser.getControl(name='type_id').value = ['Link']
        self.browser.getControl('Cancel').click()
        self.assertIn('@@overview-controlpanel', self.browser.url)

    def test_standard_type_allow_commenting(self):
        self.browser.open(self.types_url)
        self.browser.getControl(name='type_id').value = ['Link']
        self.browser.getForm(action=self.types_url).submit()
        self.browser.getControl('Allow comments').selected = True
        self.browser.getControl('Save').click()

        # Check if settings got saved correctly
        self.browser.open(self.types_url)
        self.browser.getControl(name='type_id').value = ['Link']
        self.browser.getForm(action=self.types_url).submit()
        self.assertIn('Globally addable', self.browser.contents)
        self.assertIn('Allow comments', self.browser.contents)
        self.assertEqual(
            self.browser.getControl('Allow comments').selected,
            True
        )
        self.assertIn('Visible in searches', self.browser.contents)
        self.assertIn(
            '<input id="redirect_links" type="checkbox" class="noborder"'
            ' name="redirect_links:boolean" checked="checked" />',
            self.browser.contents)
        self.assertIn(
            '<label for="redirect_links">Redirect immediately to link target',
            self.browser.contents
        )

    def test_standard_types_redirect_links(self):
        self.browser.open(self.types_url)
        self.browser.getControl(name='type_id').value = ['Link']
        self.browser.getForm(action=self.types_url).submit()
        self.browser.getControl(
            'Redirect immediately to link target'
        ).selected = True
        self.browser.getControl('Save').click()

        # Check if settings got saved correctly
        self.browser.open(self.types_url)
        self.browser.getControl(name='type_id').value = ['Link']
        self.browser.getForm(action=self.types_url).submit()
        self.assertTrue(
            'Redirect immediately to link target' in self.browser.contents
        )
        self.assertEqual(
            self.browser.getControl(
                'Redirect immediately to link target').selected,
            True
        )

    def test_set_no_default_workflow(self):
        # references http://dev.plone.org/plone/ticket/11901
        self.browser.open(self.types_url)
        self.browser.getControl(name="new_workflow").value = ['[none]']
        self.browser.getControl(name="form.button.Save").click()

        # Check that setting No workflow as default workflow doesn't break
        # break editing types
        self.browser.open(self.types_url)
        self.browser.getControl(name='type_id').value = ['Link']
        self.browser.getForm(action=self.types_url).submit()
        self.assertIn('Globally addable', self.browser.contents)
        self.assertIn('Allow comments', self.browser.contents)
        self.assertIn('Visible in searches', self.browser.contents)

    def test_disable_versioning_removes_behavior(self):
        self.browser.open(self.types_url)
        self.browser.getControl(name='type_id').value = ['Document']
        self.browser.getForm(action=self.types_url).submit()
        self.browser.getControl(name='versionpolicy').value = ['off']
        self.browser.getForm(action=self.types_url).submit()

        portal_types = self.portal.portal_types
        doc_type = portal_types.Document
        self.assertTrue(
            'plone.app.versioningbehavior.behaviors.IVersionable'
            not in doc_type.behaviors)  # noqa

    def test_enable_versioning_behavior_on_document(self):
        self.browser.open(self.types_url)
        self.browser.getControl(name='type_id').value = ['Document']
        self.browser.getForm(action=self.types_url).submit()
        self.browser.getControl(name='versionpolicy').value = ['off']
        self.browser.getForm(action=self.types_url).submit()

        portal_types = self.portal.portal_types
        doc_type = portal_types.Document
        self.assertTrue(
            'plone.app.versioningbehavior.behaviors.IVersionable'
            not in doc_type.behaviors)  # noqa

        self.browser.getControl(name='versionpolicy').value = ['manual']
        self.browser.getForm(action=self.types_url).submit()

        self.assertTrue(
            'plone.app.versioningbehavior.behaviors.IVersionable'
            in doc_type.behaviors)

    def test_enable_versioning_behavior_on_file(self):
        self.browser.open(self.types_url)
        self.browser.getControl(name='type_id').value = ['File']
        self.browser.getForm(action=self.types_url).submit()
        self.browser.getControl(name='versionpolicy').value = ['off']
        self.browser.getForm(action=self.types_url).submit()

        portal_types = self.portal.portal_types
        file_type = portal_types.File

        # File has no Versioning and no Locking on default, but needs it
        self.assertTrue(
            'plone.app.versioningbehavior.behaviors.IVersionable'
            not in file_type.behaviors)  # noqa
        self.assertTrue(
            'plone.app.lockingbehavior.behaviors.ILocking'
            not in file_type.behaviors)  # noqa

        self.browser.getControl(name='versionpolicy').value = ['manual']
        self.browser.getForm(action=self.types_url).submit()

        self.assertTrue(
            'plone.app.versioningbehavior.behaviors.IVersionable'
            in file_type.behaviors)
        self.assertTrue(
            'plone.app.lockingbehavior.behaviors.ILocking'
            in file_type.behaviors)
class SiteControlPanelFunctionalTest(unittest.TestCase):
    """Test that changes in the site control panel are actually
    stored in the registry.
    """

    layer = PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING

    def setUp(self):
        self.app = self.layer['app']
        self.portal = self.layer['portal']
        self.request = self.layer['request']
        self.portal_url = self.portal.absolute_url()
        self.browser = Browser(self.app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization', 'Basic %s:%s' % (
                SITE_OWNER_NAME,
                SITE_OWNER_PASSWORD,
            ))

    def test_site_control_panel_link(self):
        self.browser.open("%s/@@overview-controlpanel" % self.portal_url)
        self.browser.getLink('Site').click()

    def test_site_control_panel_backlink(self):
        self.browser.open("%s/@@site-controlpanel" % self.portal_url)
        self.assertTrue("General" in self.browser.contents)

    def test_site_control_panel_sidebar(self):
        self.browser.open("%s/@@site-controlpanel" % self.portal_url)
        self.browser.getLink('Site Setup').click()
        self.assertTrue(
            self.browser.url.endswith('/plone/@@overview-controlpanel'))

    def test_site_controlpanel_view(self):
        view = getMultiAdapter((self.portal, self.portal.REQUEST),
                               name="site-controlpanel")
        self.assertTrue(view())

    def test_site_title_is_stored_in_registry(self):
        self.browser.open("%s/@@site-controlpanel" % self.portal_url)
        self.browser.getControl('Site title').value = u"My Site"
        self.browser.getControl('Save').click()

        registry = getUtility(IRegistry)
        settings = registry.forInterface(ISiteSchema, prefix="plone")
        self.assertEqual(settings.site_title, u"My Site")

    def test_site_title_can_be_looked_up_by_plone_portal_state(self):
        self.browser.open("%s/@@site-controlpanel" % self.portal_url)
        self.browser.getControl('Site title').value = u"My Site"
        self.browser.getControl('Save').click()

        portal_state = getMultiAdapter((self.portal, self.request),
                                       name=u'plone_portal_state')
        self.assertEqual(portal_state.portal_title(), u'My Site')

    @unittest.skip("XXX: TODO! We have to patch CMFDefault for this.")
    def test_site_title_can_be_looked_up_by_portal_title(self):
        self.browser.open("%s/@@site-controlpanel" % self.portal_url)
        self.browser.getControl('Site title').value = u"My Site"
        self.browser.getControl('Save').click()

        self.assertEqual(self.portal.title, u'My Site')
        self.assertEqual(self.portal.Title(), u'My Site')

    def test_site_logo_is_stored_in_registry(self):
        self.browser.open("%s/@@site-controlpanel" % self.portal_url)
        ctrl = self.browser.getControl(name="form.widgets.site_logo")
        ctrl.add_file(BytesIO(SITE_LOGO_HEX), 'image/png', 'pixel.png')
        self.browser.getControl('Save').click()

        registry = getUtility(IRegistry)
        settings = registry.forInterface(ISiteSchema, prefix='plone')
        self.assertEqual(settings.site_logo, SITE_LOGO_BASE64)

    def test_exposeDCMetaTags(self):
        self.browser.open("%s/@@site-controlpanel" % self.portal_url)
        self.browser.getControl('Site title').value = u"Plone Site"
        self.browser.getControl('Expose Dublin Core metadata').selected = True
        self.browser.getControl('Save').click()

        registry = getUtility(IRegistry)
        settings = registry.forInterface(ISiteSchema, prefix="plone")
        self.assertEqual(settings.exposeDCMetaTags, True)

    def test_exposeDCMetaTags_exposes_meta_tags(self):
        self.browser.open("%s/@@site-controlpanel" % self.portal_url)
        self.browser.getControl('Site title').value = u"Plone Site"
        self.browser.getControl('Expose Dublin Core metadata').selected = True
        self.browser.getControl('Save').click()

        self.browser.open(self.portal_url)

        self.assertTrue('DC.type' in self.browser.contents)

    def test_enable_sitemap(self):
        self.browser.open("%s/@@site-controlpanel" % self.portal_url)
        self.browser.getControl('Site title').value = u"Plone Site"
        self.browser.getControl('Expose sitemap.xml.gz').selected = True
        self.browser.getControl('Save').click()

        registry = getUtility(IRegistry)
        settings = registry.forInterface(ISiteSchema, prefix="plone")
        self.assertEqual(settings.enable_sitemap, True)

    def test_enable_sitemap_enables_the_sitemap(self):
        self.browser.open("%s/@@site-controlpanel" % self.portal_url)
        self.browser.getControl('Site title').value = u"Plone Site"
        self.browser.getControl('Expose sitemap.xml.gz').selected = True
        self.browser.getControl('Save').click()

        self.browser.open("%s/sitemap.xml.gz" % self.portal_url)

        self.assertEqual(self.browser.headers['status'].lower(), '200 ok')
        self.assertEqual(self.browser.headers['content-type'],
                         'application/octet-stream')

    def test_webstats_js(self):
        self.browser.open("%s/@@site-controlpanel" % self.portal_url)
        self.browser.getControl('Site title').value = u"Plone Site"
        self.browser.getControl(name='form.widgets.webstats_js').value = \
            u"<script>a=1</script>"
        self.browser.getControl('Save').click()

        registry = getUtility(IRegistry)
        settings = registry.forInterface(ISiteSchema, prefix="plone")
        self.assertEqual(settings.webstats_js, u"<script>a=1</script>")

    def test_webstat_js_shows_up_on_site(self):
        self.browser.open("%s/@@site-controlpanel" % self.portal_url)
        self.browser.getControl('Site title').value = u"Plone Site"
        self.browser.getControl(name='form.widgets.webstats_js').value = \
            u"<script>a=1</script>"
        self.browser.getControl('Save').click()

        registry = getUtility(IRegistry)
        settings = registry.forInterface(ISiteSchema, prefix="plone")
        self.assertEqual(settings.webstats_js, u"<script>a=1</script>")
        self.browser.open(self.portal_url)

        self.assertTrue("<script>a=1</script>" in self.browser.contents)
class MarkupControlPanelFunctionalTest(unittest.TestCase):
    """Make sure changes in the markup control panel are properly
    stored in plone.app.registry.
    """

    layer = PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING

    def setUp(self):
        self.app = self.layer['app']
        self.portal = self.layer['portal']
        self.portal_url = self.portal.absolute_url()
        self.browser = Browser(self.app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization',
            'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)
        )

    def test_markup_control_panel_link(self):
        self.browser.open(
            "%s/@@overview-controlpanel" % self.portal_url)
        self.browser.getLink('Markup').click()

    def test_markup_control_panel_backlink(self):
        self.browser.open(
            "%s/@@markup-controlpanel" % self.portal_url)
        self.assertTrue("Content" in self.browser.contents)

    def test_markup_control_panel_sidebar(self):
        self.browser.open(
            "%s/@@markup-controlpanel" % self.portal_url)
        self.browser.getLink('Site Setup').click()
        self.assertTrue(
            self.browser.url.endswith('/plone/@@overview-controlpanel')
        )

    def test_markup_controlpanel_view(self):
        view = getMultiAdapter((self.portal, self.portal.REQUEST),
                               name="markup-controlpanel")
        self.assertTrue(view())

    def test_default_type(self):
        self.browser.open(
            "%s/@@markup-controlpanel" % self.portal_url)
        self.browser.getControl('Default format').value = ['text/plain']
        self.browser.getControl('Save').click()

        registry = getUtility(IRegistry)
        settings = registry.forInterface(IMarkupSchema, prefix='plone')
        self.assertEqual(settings.default_type, 'text/plain')

    def test_allowed_types(self):
        self.browser.open(
            "%s/@@markup-controlpanel" % self.portal_url)
        self.browser.getControl(
            name='form.widgets.allowed_types:list'
        ).value = ['text/html', 'text/x-web-textile']
        self.browser.getControl('Save').click()

        registry = getUtility(IRegistry)
        settings = registry.forInterface(IMarkupSchema, prefix='plone')
        self.assertEqual(settings.allowed_types,
                         ('text/html', 'text/x-web-textile'))
Esempio n. 36
0
class ActionsDXTestCase(unittest.TestCase):

    layer = PLONE_APP_CONTENT_DX_FUNCTIONAL_TESTING

    def setUp(self):
        self.portal = self.layer['portal']
        self.request = self.layer['request']

        self.portal.acl_users.userFolderAddUser('editor', 'secret', ['Editor'],
                                                [])

        # For z3c.forms request must provide IFormLayer
        alsoProvides(self.request, IFormLayer)

        setRoles(self.portal, TEST_USER_ID, ['Manager'])
        self.portal.invokeFactory(type_name='Folder',
                                  id='f1',
                                  title='A Tést Folder')

        transaction.commit()
        self.browser = Browser(self.layer['app'])
        self.browser.handleErrors = False
        self.browser.addHeader('Authorization',
                               'Basic {}:{}'.format(TEST_USER_NAME, 'secret'))

    def tearDown(self):
        if 'f1' in self.portal.objectIds():
            self.portal.manage_delObjects(ids='f1')
            transaction.commit()

    def test_delete_confirmation(self):
        folder = self.portal['f1']

        form = getMultiAdapter((folder, self.request),
                               name='delete_confirmation')
        form.update()

        cancel = form.buttons['Cancel']
        form.handlers.getHandler(cancel)(form, form)

        self.assertFalse(form.is_locked)

    def test_delete_confirmation_if_locked(self):
        folder = self.portal['f1']
        lockable = ILockable.providedBy(folder)

        form = getMultiAdapter((folder, self.request),
                               name='delete_confirmation')
        form.update()

        self.assertFalse(form.is_locked)

        if lockable:
            lockable.lock()

        form = getMultiAdapter((folder, self.request),
                               name='delete_confirmation')
        form.update()

        self.assertFalse(form.is_locked)

        # After switching the user it should not be possible to delete the
        # object. Of course this is only possible if our context provides
        # ILockable interface.
        if lockable:
            logout()
            login(self.portal, 'editor')

            form = getMultiAdapter((folder, self.request),
                                   name='delete_confirmation')
            form.update()
            self.assertTrue(form.is_locked)

            logout()
            login(self.portal, TEST_USER_NAME)

            ILockable(folder).unlock()

    def test_delete_confirmation_cancel(self):
        folder = self.portal['f1']

        self.browser.open(folder.absolute_url() + '/delete_confirmation')
        self.browser.getControl(name='form.buttons.Cancel').click()
        context_state = getMultiAdapter((folder, self.request),
                                        name='plone_context_state')
        self.assertEqual(self.browser.url, context_state.view_url())

    def prepare_for_acquisition_tests(self):
        """create content and an alternate authenticated browser session

        creates the following content structure:

        |-- f1
        |   |-- test
        |-- test
        """
        # create a page at the root and one nested with the same id.
        p1 = self.portal.invokeFactory(type_name='Document',
                                       id='test',
                                       title='Test Page at Root')
        folder_1 = self.portal['f1']
        p2 = folder_1.invokeFactory(type_name='Document',
                                    id='test',
                                    title='Test Page in Folder')
        contained_test_page = folder_1[p2]

        transaction.commit()

        # create an alternate browser also logged in with manager
        browser_2 = Browser(self.layer['app'])
        browser_2.handleErrors = False
        browser_2.addHeader('Authorization',
                            'Basic {}:{}'.format(TEST_USER_NAME, 'secret'))

        # return the id of the root page, the nested page itself, and the
        # alternate browser
        return p1, contained_test_page, browser_2

    def test_delete_wrong_object_by_acquisition_with_action(self):
        """exposes delete-by-acquisition bug using the delete action

        see https://github.com/plone/Products.CMFPlone/issues/383
        """
        p1_id, page_2, browser_2 = self.prepare_for_acquisition_tests()

        # open two different browsers to the 'delete confirmation' view
        delete_url = page_2.absolute_url() + '/delete_confirmation'
        self.browser.open(delete_url)
        browser_2.open(delete_url)
        self.assertTrue(p1_id in self.portal)
        for browser in [self.browser, browser_2]:
            browser.getControl(name='form.buttons.Delete').click()

        # the nested folder should be gone, but the one at the root should
        # remain.
        self.assertFalse(page_2.id in self.portal['f1'])
        self.assertTrue(p1_id in self.portal)

    def test_rename_form(self):
        logout()
        folder = self.portal['f1']

        # We need zope2.CopyOrMove permission to rename content
        self.browser.open(folder.absolute_url() + '/folder_rename')
        self.browser.getControl(name='form.widgets.new_id').value = 'f2'
        self.browser.getControl(name='form.widgets.new_title').value = 'F2'
        self.browser.getControl(name='form.buttons.Rename').click()
        self.assertEqual(folder.getId(), 'f2')
        self.assertEqual(folder.Title(), 'F2')
        self.assertEqual(self.browser.url, folder.absolute_url())

        login(self.portal, TEST_USER_NAME)
        self.portal.manage_delObjects(ids='f2')
        transaction.commit()

    def test_rename_form_with_view_action(self):
        # can't be bothered to register blobs, instead we add documents to
        # typesUseViewActionInListings
        registry = self.portal.portal_registry
        registry['plone.types_use_view_action_in_listings'] = [
            'Image', 'File', 'Document'
        ]

        folder = self.portal['f1']
        folder.invokeFactory('Document', 'document1')
        document1 = folder['document1']
        transaction.commit()
        logout()

        # We need zope2.CopyOrMove permission to rename content
        self.browser.open(document1.absolute_url() + '/object_rename')
        self.browser.getControl(name='form.widgets.new_id').value = 'f2'
        self.browser.getControl(name='form.widgets.new_title').value = 'F2'
        self.browser.getControl(name='form.buttons.Rename').click()
        self.assertEqual(document1.getId(), 'f2')
        self.assertEqual(document1.Title(), 'F2')
        self.assertEqual(self.browser.url, document1.absolute_url() + '/view')

        login(self.portal, TEST_USER_NAME)
        self.portal.manage_delObjects(ids='f1')
        transaction.commit()

    def test_create_safe_id_on_renaming(self):
        logout()
        folder = self.portal['f1']

        # We need zope2.CopyOrMove permission to rename content
        self.browser.open(folder.absolute_url() + '/folder_rename')
        self.browser.getControl(name='form.widgets.new_id').value = ' ? f4 4 '
        self.browser.getControl(name='form.widgets.new_title').value = ' F2 '
        self.browser.getControl(name='form.buttons.Rename').click()
        self.assertEqual(folder.getId(), 'f4-4')
        self.assertEqual(folder.Title(), 'F2')
        self.assertEqual(self.browser.url, folder.absolute_url())

        login(self.portal, TEST_USER_NAME)
        self.portal.manage_delObjects(ids='f4-4')
        transaction.commit()

    def test_default_page_updated_on_rename(self):
        login(self.portal, TEST_USER_NAME)
        folder = self.portal['f1']
        folder.invokeFactory(type_name='Document', id='d1', title='A Doc')
        doc = folder['d1']
        folder.setDefaultPage('d1')
        transaction.commit()
        self.assertEqual(folder.getDefaultPage(), 'd1')

        # We need zope2.CopyOrMove permission to rename content
        self.browser.open(doc.absolute_url() + '/object_rename')
        self.browser.getControl(name='form.widgets.new_id').value = ' ?renamed'
        self.browser.getControl(name='form.widgets.new_title').value = 'Doc'
        self.browser.getControl(name='form.buttons.Rename').click()
        self.assertEqual(folder.getFolderContents()[0].id, 'renamed')
        self.assertEqual(folder.getDefaultPage(), 'renamed')

    def test_rename_form_cancel(self):
        folder = self.portal['f1']

        _id = folder.getId()
        _title = folder.Title()

        self.browser.open(folder.absolute_url() + '/folder_rename')
        self.browser.getControl(name='form.buttons.Cancel').click()
        transaction.commit()

        self.assertEqual(self.browser.url, folder.absolute_url())
        self.assertEqual(folder.getId(), _id)
        self.assertEqual(folder.Title(), _title)

    def test_rename_form_cancel_with_view_action(self):
        # can't be bothered to register blobs, instead we add documents to
        # typesUseViewActionInListings
        registry = self.portal.portal_registry
        registry['plone.types_use_view_action_in_listings'] = [
            'Image', 'File', 'Document'
        ]
        folder = self.portal['f1']
        folder.invokeFactory('Document', 'document1')
        document1 = folder['document1']
        transaction.commit()

        _id = document1.getId()
        _title = document1.Title()

        self.browser.open(document1.absolute_url() + '/object_rename')
        self.browser.getControl(name='form.buttons.Cancel').click()
        transaction.commit()

        self.assertEqual(self.browser.url, document1.absolute_url() + '/view')
        self.assertEqual(document1.getId(), _id)
        self.assertEqual(document1.Title(), _title)

    def _get_token(self, context):
        authenticator = getMultiAdapter((context, self.request),
                                        name='authenticator')

        return authenticator.token()

    def test_object_cut_view(self):
        folder = self.portal['f1']

        # We need pass an authenticator token to prevent Unauthorized
        self.assertRaises(Unauthorized, self.browser.open,
                          f'{folder.absolute_url():s}/object_cut')

        # We need to have Copy or Move permission to cut an object
        self.browser.open('{:s}/object_cut?_authenticator={:s}'.format(
            folder.absolute_url(), self._get_token(folder)))

        self.assertIn('__cp', self.browser.cookies)
        self.assertIn(f'{folder.Title():s} cut.', self.browser.contents)

    def test_object_cut_view_with_view_action(self):
        # can't be bothered to register blobs, instead we add documents to
        # typesUseViewActionInListings
        registry = self.portal.portal_registry
        registry['plone.types_use_view_action_in_listings'] = [
            'Image', 'File', 'Document'
        ]
        folder = self.portal['f1']
        folder.invokeFactory('Document', 'document1')
        document1 = folder['document1']
        transaction.commit()

        # We need pass an authenticator token to prevent Unauthorized
        self.assertRaises(Unauthorized, self.browser.open,
                          f'{document1.absolute_url():s}/object_cut')

        # We need to have Copy or Move permission to cut an object
        self.browser.open('{:s}/object_cut?_authenticator={:s}'.format(
            document1.absolute_url(), self._get_token(document1)))

        self.assertIn('__cp', self.browser.cookies)
        self.assertIn(f'{document1.Title():s} cut.', self.browser.contents)
        self.assertEqual(document1.absolute_url() + '/view', self.browser.url)

    def test_object_copy_view(self):
        folder = self.portal['f1']

        # We need pass an authenticator token to prevent Unauthorized
        self.assertRaises(Unauthorized, self.browser.open,
                          f'{folder.absolute_url():s}/object_copy')

        self.browser.open('{:s}/object_copy?_authenticator={:s}'.format(
            folder.absolute_url(), self._get_token(folder)))

        self.assertIn('__cp', self.browser.cookies)
        self.assertIn(f'{folder.Title():s} copied.', self.browser.contents)

    def test_object_copy_with_view_action(self):
        # can't be bothered to register blobs, instead we add documents to
        # typesUseViewActionInListings
        registry = self.portal.portal_registry
        registry['plone.types_use_view_action_in_listings'] = [
            'Image', 'File', 'Document'
        ]

        folder = self.portal['f1']
        folder.invokeFactory('Document', 'document1')
        document1 = folder['document1']
        transaction.commit()

        # We need pass an authenticator token to prevent Unauthorized
        self.assertRaises(Unauthorized, self.browser.open,
                          f'{document1.absolute_url():s}/object_copy')

        self.browser.open('{:s}/object_copy?_authenticator={:s}'.format(
            document1.absolute_url(), self._get_token(document1)))

        self.assertIn('__cp', self.browser.cookies)
        self.assertIn(f'{document1.Title():s} copied.', self.browser.contents)
        self.assertEqual(document1.absolute_url() + '/view', self.browser.url)

    def test_object_cut_and_paste(self):
        folder = self.portal['f1']
        self.portal.invokeFactory(type_name='Document', id='d1', title='A Doc')
        doc = self.portal['d1']
        transaction.commit()

        self.browser.open('{:s}/object_cut?_authenticator={:s}'.format(
            doc.absolute_url(), self._get_token(doc)))

        self.assertIn('__cp', self.browser.cookies)
        self.assertIn('d1', self.portal.objectIds())
        self.assertIn('f1', self.portal.objectIds())

        # We need pass an authenticator token to prevent Unauthorized
        self.assertRaises(Unauthorized, self.browser.open,
                          f'{folder.absolute_url():s}/object_paste')

        self.browser.open('{:s}/object_paste?_authenticator={:s}'.format(
            folder.absolute_url(), self._get_token(doc)))

        self.assertIn('__cp', self.browser.cookies)
        transaction.commit()

        self.assertNotIn('d1', self.portal.objectIds())
        self.assertIn('d1', folder.objectIds())
        self.assertIn('Item(s) pasted.', self.browser.contents)

    def test_object_copy_and_paste(self):
        folder = self.portal['f1']
        folder.invokeFactory(type_name='Document', id='d1', title='A Doc')
        doc = folder['d1']
        transaction.commit()

        self.browser.open('{:s}/object_copy?_authenticator={:s}'.format(
            doc.absolute_url(), self._get_token(doc)))

        self.assertIn('__cp', self.browser.cookies)

        # We need pass an authenticator token to prevent Unauthorized
        self.assertRaises(Unauthorized, self.browser.open,
                          f'{folder.absolute_url():s}/object_paste')

        self.browser.open('{:s}/object_paste?_authenticator={:s}'.format(
            folder.absolute_url(), self._get_token(folder)))
        transaction.commit()

        self.assertIn('f1', self.portal.objectIds())
        self.assertIn('d1', folder.objectIds())
        self.assertIn('copy_of_d1', folder.objectIds())
        self.assertIn('Item(s) pasted.', self.browser.contents)

    def test_object_copy_and_paste_multiple_times(self):
        folder = self.portal['f1']
        folder.invokeFactory(type_name='Document', id='d1', title='A Doc')
        doc = folder['d1']
        transaction.commit()

        self.browser.open('{:s}/object_copy?_authenticator={:s}'.format(
            doc.absolute_url(), self._get_token(doc)))

        self.assertIn('__cp', self.browser.cookies)
        self.browser.open('{:s}/object_paste?_authenticator={:s}'.format(
            folder.absolute_url(), self._get_token(folder)))
        self.browser.open('{:s}/object_paste?_authenticator={:s}'.format(
            folder.absolute_url(), self._get_token(folder)))

        # Cookie should persist, because you can paste the item multiple times
        self.assertIn('__cp', self.browser.cookies)
        self.assertIn('f1', self.portal.objectIds())
        self.assertIn('d1', folder.objectIds())
        self.assertIn('copy_of_d1', folder.objectIds())
        self.assertIn('copy2_of_d1', folder.objectIds())
        self.assertIn('Item(s) pasted.', self.browser.contents)
class AddonsControlPanelFunctionalTest(unittest.TestCase):
    """Test that the add-ons control panel works nicely."""

    layer = PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING

    def setUp(self):
        self.app = self.layer['app']
        self.portal = self.layer['portal']
        self.portal_url = self.portal.absolute_url()
        self.browser = Browser(self.app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization',
            'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)
        )

    def test_addons_controlpanel_link(self):
        self.browser.open(
            '%s/@@overview-controlpanel' % self.portal_url)
        self.browser.getLink('Add-ons').click()

    def test_addons_controlpanel_backlink(self):
        self.browser.open(
            '%s/prefs_install_products_form' % self.portal_url)
        self.assertTrue('General' in self.browser.contents)

    def test_addons_controlpanel_sidebar(self):
        self.browser.open(
            '%s/prefs_install_products_form' % self.portal_url)
        self.browser.getLink('Site Setup').click()
        self.assertTrue(
            self.browser.url.endswith('/plone/@@overview-controlpanel')
        )

    def test_addons_controlpanel_view(self):
        view = getMultiAdapter((self.portal, self.portal.REQUEST),
                               name='prefs_install_products_form')
        self.assertTrue(view())

    def test_addons_controlpanel_no_upgrades(self):
        self.browser.open(
            '%s/prefs_install_products_form' % self.portal_url)
        self.assertIn('No upgrades in this corner', self.browser.contents)

    def test_addons_controlpanel_installable(self):
        self.browser.open(
            '%s/prefs_install_products_form' % self.portal_url)
        # We expect a few standard add-ons.
        self.assertIn('Workflow Policy Support', self.browser.contents)
        self.assertIn('Multilingual Support', self.browser.contents)
        self.assertIn('plone.session', self.browser.contents)

    def test_addons_controlpanel_not_installable(self):
        self.browser.open(
            '%s/prefs_install_products_form' % self.portal_url)
        # We do not expect some other add-ons.
        self.assertNotIn('plone.app.upgrade', self.browser.contents)
        self.assertNotIn('Products.CMFPlone', self.browser.contents)

    def test_addons_controlpanel_install_and_uninstall_all(self):
        self.browser.open(
            '%s/prefs_install_products_form' % self.portal_url)
        self.assertNotIn('Installed', self.browser.contents)
        self.assertNotIn('Uninstalled', self.browser.contents)
        # It is hard to determine which exact product will be installed
        # by clicking on a button, because they are all called 'Install'.
        # We install all available products.
        for buttons in range(12):
            try:
                self.browser.getControl('Install', index=buttons)
            except LookupError:
                break
        else:
            # Either our test logic is off, or the code that determines
            # which products are installable is actually wrong.
            raise AssertionError('Too many Install buttons.')
        # Click all install buttons.
        for button in range(buttons):
            # Always install the first.
            self.browser.getControl('Install', index=0).click()
            self.assertIn('Installed', self.browser.contents)
        # There are no more install buttons.
        with self.assertRaises(LookupError):
            self.browser.getControl('Install', index=0)
        # There should now be just as many Uninstall buttons.
        self.browser.getControl('Uninstall', index=buttons - 1)
        for button in range(buttons):
            # Always uninstall the first.
            self.browser.getControl('Uninstall', index=0).click()
            self.assertIn('Uninstalled', self.browser.contents)
        # There are no more uninstall buttons.
        with self.assertRaises(LookupError):
            self.browser.getControl('Uninstall', index=0)
        # Instead, we could install all again if we want.
        self.browser.getControl('Install', index=buttons - 1)
class UserGroupsControlPanelFunctionalTest(unittest.TestCase):
    """Test that changes in the user groups control panel are actually
    creating and changing users and groups.
    """

    layer = PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING

    def _generateGroups(self):
        groupsTool = getToolByName(self.portal, 'portal_groups')
        self.groups = [{
            'id': 'group1',
            'title': "Group 1"
        }, {
            'id': 'group2',
            'title': "Group 2"
        }, {
            'id': 'group3',
            'title': "Group 3 accentué"
        }]
        for group in self.groups:
            groupsTool.addGroup(group['id'], [], [], title=group['title'])

    def _generateUsers(self):
        self.members = [
            {
                'username': '******',
                'fullname': 'Kevin Hughes',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Richard Ramirez',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Kyle Brown',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Julian Green',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Makayla Coleman',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Sean Foster',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Molly Martin',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Jordan Thompson',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Tyler Rivera',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Megan Murphy',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Gracie Diaz',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Rachel Morgan',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Maya Price',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Blake Jenkins',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Owen Ramirez',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Owen Cook',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Jayden Hill',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Joseph Ramirez',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Nathan Young',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Kaitlyn Hernandez',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Faith Price',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Sofia Williams',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'David Sanders',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Jack Simmons',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Cole Howard',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Rachel Miller',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Henry Patterson',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Avery Cooper',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Sydney Bennett',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Daniel Johnson',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Autumn Brooks',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Alexandra Nelson',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Brian Simmons',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Kevin Hughes',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Sydney Evans',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Emma Brown',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Lauren Martin',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Isabelle Russell',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Anna Baker',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Brady Watson',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Kaitlyn Robinson',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Riley Richardson',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Kayla Sanders',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Sara Richardson',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Trinity Gonzales',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Madeline Garcia',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Brian Gray',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Victoria Perez',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Charles Rodriguez',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Abigail Simmons',
                'email': '*****@*****.**'
            },
            {
                'username': '******',
                'fullname': 'Émilie Richard',
                'email': '*****@*****.**'
            },
        ]
        rtool = getToolByName(self.portal, 'portal_registration')
        for member in self.members:
            rtool.addMember(member['username'],
                            'somepassword',
                            properties=member)

    def setUp(self):
        self.app = self.layer['app']
        self.portal = self.layer['portal']
        self.portal_url = self.portal.absolute_url()
        self.usergroups_url = "%s/@@usergroup-userprefs" % self.portal_url
        self.groups_url = "%s/@@usergroup-groupprefs" % self.portal_url
        self._generateGroups()
        self._generateUsers()
        transaction.commit()

        self.browser = Browser(self.app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization', 'Basic %s:%s' % (
                SITE_OWNER_NAME,
                SITE_OWNER_PASSWORD,
            ))

    def test_usergroups_control_panel_link(self):
        self.browser.open("%s/@@overview-controlpanel" % self.portal_url)
        self.browser.getLink('Users and Groups').click()
        self.assertEqual(self.browser.url, self.usergroups_url)

    def test_usergroups_groups_link(self):
        self.browser.open(self.usergroups_url)
        self.browser.getLink('Groups', index=0).click()
        self.assertEqual(self.browser.url,
                         "%s/@@usergroup-groupprefs" % self.portal_url)

    def test_usergroups_settings_link(self):
        self.browser.open(self.usergroups_url)
        self.browser.getLink('Settings').click()
        self.assertEqual(self.browser.url,
                         "%s/@@usergroup-controlpanel" % self.portal_url)

    def test_usergroups_memberfields_link(self):
        self.browser.open(self.usergroups_url)
        self.browser.getLink('Member fields').click()
        self.assertEqual(self.browser.url,
                         "%s/@@member-fields" % self.portal_url)

    def test_user_search_by_name(self):
        self.browser.open(self.usergroups_url)
        self.browser.getControl(name='searchstring').value = 'Richard'
        self.browser.getControl(name='form.button.Search').click()
        self.assertIn('Richard Ramirez', self.browser.contents)
        self.assertIn('Sara Richardson', self.browser.contents)
        self.assertIn('Émilie Richard', self.browser.contents)

    def test_user_search_by_name_accent(self):
        self.browser.open(self.usergroups_url)
        self.browser.getControl(name='searchstring').value = 'Émilie'
        self.browser.getControl(name='form.button.Search').click()
        self.assertIn('Émilie Richard', self.browser.contents)

    def test_user_search_by_id(self):
        self.browser.open(self.usergroups_url)
        self.browser.getControl(name='searchstring').value = 'TWrMCLIo'
        self.browser.getControl(name='form.button.Search').click()
        self.assertIn('Autumn Brooks', self.browser.contents)

    def test_user_search_by_mail(self):
        self.browser.open(self.usergroups_url)
        self.browser.getControl(name='searchstring').value = 'DohPmgIa@'
        self.browser.getControl(name='form.button.Search').click()
        self.assertIn('Gracie Diaz', self.browser.contents)

    def test_user_show_all(self):
        self.browser.open(self.usergroups_url)
        self.browser.getControl(name='form.button.FindAll').click()

        # Check that first 10 members (sorted by fullname) are shown.
        for member in sorted(
                self.members,
                key=lambda k: normalizeString(k['fullname']))[:10]:
            self.assertIn(member['fullname'], self.browser.contents)

    def test_user_show_all_with_search_term(self):
        self.browser.open(self.usergroups_url)
        self.browser.getControl(name='searchstring').value = 'no-user'
        self.browser.getControl(name='form.button.FindAll').click()

        # Check that all members is shown and search term is ignored
        self.assertIn('Avery Cooper', self.browser.contents)

    def test_user_add_new_link(self):
        self.browser.open(self.usergroups_url)
        self.browser.getLink(id='add-user').click()
        self.assertEqual(self.browser.url, "%s/@@new-user" % self.portal_url)

    def test_user_modify_roles(self):
        self.browser.open(self.usergroups_url)
        self.browser.getControl(name='searchstring').value = 'TWrMCLIo'
        self.browser.getControl(name='form.button.Search').click()

        # Check that contributor role is not enabled and enable it
        self.assertFalse(
            self.browser.getControl(
                name='users.roles:list:records').getControl(
                    value='Contributor').selected)
        self.browser.getControl(name='users.roles:list:records').getControl(
            value='Contributor').selected = True
        self.browser.getControl(name='form.button.Modify').click()

        # Check that contributor role is now enabled for this user
        self.browser.open(self.usergroups_url)
        self.browser.getControl(name='searchstring').value = 'TWrMCLIo'
        self.browser.getControl(name='form.button.Search').click()
        self.assertTrue(
            self.browser.getControl(
                name='users.roles:list:records').getControl(
                    value='Contributor').selected)

    def test_user_delete(self):
        self.browser.open(self.usergroups_url)
        self.browser.getControl(name='searchstring').value = 'TWrMCLIo'
        self.browser.getControl(name='form.button.Search').click()
        self.assertIn('Autumn Brooks', self.browser.contents)

        # Delete user
        self.browser.getControl(name='delete:list').getControl(
            value='TWrMCLIo').selected = True
        self.browser.getControl(name='form.button.Modify').click()

        # Check that user does not exist anymore
        self.browser.getControl(name='searchstring').value = 'TWrMCLIo'
        self.browser.getControl(name='form.button.Search').click()
        self.assertNotIn('Autumn Brooks', self.browser.contents)

    def test_groups_search_by_id(self):
        self.browser.open(self.groups_url)
        self.browser.getControl(name='searchstring').value = 'group1'
        self.browser.getControl(name='form.button.Search').click()
        self.assertIn('Group 1', self.browser.contents)

    def test_groups_search_by_name(self):
        self.browser.open(self.groups_url)
        self.browser.getControl(name='searchstring').value = 'Group 3 accentué'
        self.browser.getControl(name='form.button.Search').click()
        self.assertIn('Group 3 accentué', self.browser.contents)

    def test_groups_modify_roles(self):
        self.browser.open(self.groups_url)
        self.browser.getControl(name='searchstring').value = 'group1'

        # Check that role is not selected yet and then select it and apply it.
        form = self.browser.getForm(id='groups_search')
        ctrls = form._form.fields.get('group_group1:list')
        roles = [ctrl._value for ctrl in ctrls]
        expected = 'Site Administrator'
        self.assertIn(expected, roles)
        idx = roles.index(expected)
        self.assertFalse(ctrls[idx].checked)
        ctrls[idx].checked = True
        self.browser.getControl('Save').click()

        # Check that role is now selected
        form = self.browser.getForm(id='groups_search')
        ctrl = form._form.get('group_group1:list', index=idx)
        self.assertEqual(ctrl._value, expected)
        self.assertTrue(ctrl.checked)

    def test_groups_delete_group(self):
        self.browser.open(self.groups_url)
        self.browser.getControl(name='searchstring').value = 'group1'

        # Delete a group
        self.browser.getControl(name='delete:list').getControl(
            value='group1').selected = True
        self.browser.getControl(name='form.button.Modify').click()

        # Check that group doesn't exist anymore
        self.browser.getControl(name='searchstring').value = 'group1'
        self.assertNotIn('Group 1', self.browser.contents)

    def test_groups_show_all(self):
        self.browser.open(self.groups_url)
        self.browser.getControl(name='form.button.FindAll').click()

        for group in self.groups:
            self.assertIn(group['title'], self.browser.contents)

    def test_group_add_users(self):
        self.browser.open(self.groups_url)
        self.browser.getLink('Group 1 (group1)').click()
        self.assertIn('There is no group or user attached to this group.',
                      self.browser.contents)

        # Add user (Autumn Brooks) to selected group (Group 1)
        self.browser.getControl(name='searchstring').value = 'TWrMCLIo'
        self.browser.getControl(name='form.button.Search').click()
        self.browser.getControl(name='add:list').getControl(
            value='TWrMCLIo').selected = True

        # Check that user is now part of the group
        self.browser.getControl(
            'Add selected groups and users to this group').click()
        self.assertIn('Autumn Brooks', self.browser.contents)

    def test_group_add_group(self):
        self.browser.open(self.groups_url)
        self.browser.getLink('Group 1 (group1)').click()
        self.assertIn('There is no group or user attached to this group.',
                      self.browser.contents)

        # Add group2 to selected  group 1
        self.browser.getControl(name='searchstring').value = 'group2'
        self.browser.getControl(name='form.button.Search').click()
        self.browser.getControl(name='add:list').getControl(
            value='group2').selected = True

        # Check that group is now part of the group
        self.browser.getControl(
            'Add selected groups and users to this group').click()
        self.assertIn('Group 2', self.browser.contents)

        # Check that you can still add a user too.  This failed at some point:
        # https://github.com/plone/Products.CMFPlone/issues/3048
        # Add user (Autumn Brooks) to selected group (Group 1)
        self.browser.getControl(name='searchstring').value = 'TWrMCLIo'
        self.browser.getControl(name='form.button.Search').click()
        self.browser.getControl(name='add:list').getControl(
            value='TWrMCLIo').selected = True
        self.browser.getControl(
            'Add selected groups and users to this group').click()

        # Check that both group and user are now part of the group
        self.browser.open(self.groups_url)
        self.browser.getLink('Group 1 (group1)').click()
        self.assertIn('Autumn Brooks', self.browser.contents)
        self.assertIn('Group 2', self.browser.contents)

    def test_usergroups_settings_many_users(self):
        self.browser.open("%s/@@usergroup-controlpanel" % self.portal_url)
        self.browser.getControl(
            name='form.widgets.many_users:list').controls[0].selected = True
        self.browser.getControl('Save').click()

        # Check that show all button for users is no longer available
        self.browser.open(self.usergroups_url)
        self.assertNotIn('Show all', self.browser.contents)

        # Check that empty search does not trigger show all
        self.browser.open(self.usergroups_url)
        self.browser.getControl(name='searchstring').value = ''

    def test_usergroups_settings_many_groups(self):
        self.browser.open("%s/@@usergroup-controlpanel" % self.portal_url)
        self.browser.getControl(
            name='form.widgets.many_groups:list').controls[0].selected = True
        self.browser.getControl('Save').click()

        # Check that show all button for groups is no longer available
        self.browser.open(self.groups_url)
        self.assertNotIn('Show all', self.browser.contents)
        self.assertNotIn('DIispfuF', self.browser.contents)
class SecurityControlPanelFunctionalTest(unittest.TestCase):
    """Test that changes in the security control panel are actually
    stored in the registry.
    """

    layer = PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING

    def setUp(self):
        self.app = self.layer['app']
        self.portal = self.layer['portal']
        self.portal_url = self.portal.absolute_url()
        registry = getUtility(IRegistry)
        self.settings = registry.forInterface(
            ISecuritySchema, prefix="plone")
        self.browser = Browser(self.app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization',
            'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)
        )

    def test_security_control_panel_link(self):
        self.browser.open(
            "%s/@@overview-controlpanel" % self.portal_url)
        self.browser.getLink('Security').click()

    def test_security_control_panel_backlink(self):
        self.browser.open(
            "%s/@@security-controlpanel" % self.portal_url)
        self.assertTrue("Security" in self.browser.contents)

    def test_security_control_panel_sidebar(self):
        self.browser.open(
            "%s/@@security-controlpanel" % self.portal_url)
        self.browser.getLink('Site Setup').click()
        self.assertTrue(
            self.browser.url.endswith('/plone/@@overview-controlpanel')
        )

    def test_enable_self_reg(self):
        self.browser.open(
            "%s/@@security-controlpanel" % self.portal_url)
        self.browser.getControl('Enable self-registration').selected = True
        self.browser.getControl('Save').click()

        self.assertEqual(self.settings.enable_self_reg, True)

    def test_enable_user_pwd_choice(self):
        self.browser.open(
            "%s/@@security-controlpanel" % self.portal_url)
        self.browser.getControl(
            'Let users select their own passwords').selected = True
        self.browser.getControl('Save').click()

        self.assertEqual(self.settings.enable_user_pwd_choice, True)

    def test_enable_user_folders(self):
        self.browser.open(
            "%s/@@security-controlpanel" % self.portal_url)
        self.browser.getControl(
            'Enable User Folders').selected = True
        self.browser.getControl('Save').click()

        self.assertEqual(self.settings.enable_user_folders, True)

    def test_allow_anon_views_about(self):
        self.browser.open(
            "%s/@@security-controlpanel" % self.portal_url)
        self.browser.getControl(
            "Allow anyone to view 'about' information").selected = True
        self.browser.getControl('Save').click()

        self.assertEqual(self.settings.allow_anon_views_about, True)

    def test_use_email_as_login(self):
        self.browser.open(
            "%s/@@security-controlpanel" % self.portal_url)
        self.browser.getControl(
            "Use email address as login name").selected = True
        self.browser.getControl('Save').click()

        self.assertEqual(self.settings.use_email_as_login, True)

    def test_use_uuid_as_userid(self):
        self.browser.open(
            "%s/@@security-controlpanel" % self.portal_url)
        self.browser.getControl(
            "Use UUID user ids").selected = True
        self.browser.getControl('Save').click()

        self.assertEqual(self.settings.use_uuid_as_userid, True)
class ImagePublisherTests(unittest.TestCase):

    layer = PLONE_NAMEDFILE_FUNCTIONAL_TESTING

    def setUp(self):
        if six.PY2:
            raise unittest.SkipTest('Disabled in py2 for now.')
        data = getFile('image.png')
        item = DummyContent()
        item.image = NamedImage(data, 'image/png', u'image.png')
        self.layer['app']._setOb('item', item)
        self.item = self.layer['app'].item
        self.view = self.item.unrestrictedTraverse('@@images')
        self._orig_sizes = ImageScaling._sizes

        self.browser = Browser(self.layer['app'])
        self.browser.handleErrors = False
        self.browser.addHeader('Referer', self.layer['app'].absolute_url())

    def tearDown(self):
        ImageScaling._sizes = self._orig_sizes

    def testPublishScaleViaUID(self):
        scale = self.view.scale('image', width=64, height=64)
        transaction.commit()
        # make sure the referenced image scale is available
        self.browser.open(scale.url)
        self.assertEqual('image/png', self.browser.headers['content-type'])
        assertImage(self, self.browser.contents, 'PNG', (64, 64))

    def testPublishWebDavScaleViaUID(self):
        scale = self.view.scale('image', width=64, height=64)
        transaction.commit()
        # make sure the referenced image scale is available
        self.browser.open(scale.url + '/manage_DAVget')
        self.assertEqual('image/png', self.browser.headers['content-type'])
        assertImage(self, self.browser.contents, 'PNG', (64, 64))

    def testPublishFTPScaleViaUID(self):
        scale = self.view.scale('image', width=64, height=64)
        transaction.commit()
        # make sure the referenced image scale is available
        self.browser.open(scale.url + '/manage_FTPget')
        self.assertIn('200', self.browser.headers['status'])
        # Same remark as in testPublishWebDavScaleViaUID is valid here.
        self.assertEqual('image/png', self.browser.headers['content-type'])
        assertImage(self, self.browser.contents, 'PNG', (64, 64))

    def testHeadRequestMethod(self):
        scale = self.view.scale('image', width=64, height=64)
        transaction.commit()
        # make sure the referenced image scale is available
        url = str(scale.url)
        self.browser.open(url)
        GET_length = len(self.browser.contents)

        self.browser = Browser(self.layer['app'])
        self.browser.handleErrors = False
        self.browser.addHeader('Referer', self.layer['app'].absolute_url())

        def make_head_request(args):
            return self.browser.testapp.head(url, **args)

        self.browser._processRequest(url, make_head_request)

        self.assertEqual('image/png', self.browser.headers['content-type'])
        self.assertEqual(
            self.browser.headers['Content-Length'],
            str(GET_length)
        )
        self.assertEqual(self.browser.contents, b'')

    def testPublishThumbViaUID(self):
        ImageScaling._sizes = {'thumb': (128, 128)}
        scale = self.view.scale('image', 'thumb')
        transaction.commit()
        # make sure the referenced image scale is available
        self.browser.open(scale.url)
        self.assertEqual('image/png', self.browser.headers['content-type'])
        assertImage(self, self.browser.contents, 'PNG', (128, 128))

    def testPublishCustomSizeViaUID(self):
        # set custom image sizes
        ImageScaling._sizes = {'foo': (23, 23)}
        scale = self.view.scale('image', 'foo')
        transaction.commit()
        # make sure the referenced image scale is available
        self.browser.open(scale.url)
        self.assertEqual('image/png', self.browser.headers['content-type'])
        assertImage(self, self.browser.contents, 'PNG', (23, 23))

    def testPublishThumbViaName(self):
        ImageScaling._sizes = {'thumb': (128, 128)}
        transaction.commit()

        # make sure traversing works as is and with scaling
        # first the field without a scale name
        self.browser.open(
            self.layer['app'].absolute_url() + '/item/@@images/image'
        )
        self.assertEqual('image/png', self.browser.headers['content-type'])
        self.assertEqual(self.browser.contents, getFile('image.png'))

        # and last a scaled version
        self.browser.open(
            self.layer['app'].absolute_url() + '/item/@@images/image/thumb'
        )
        self.assertEqual('image/png', self.browser.headers['content-type'])
        assertImage(self, self.browser.contents, 'PNG', (128, 128))

    def testPublishCustomSizeViaName(self):
        # set custom image sizes
        ImageScaling._sizes = {'foo': (23, 23)}
        transaction.commit()
        # make sure traversing works as expected
        self.browser.open(
            self.layer['app'].absolute_url() + '/item/@@images/image/foo'
        )
        assertImage(self, self.browser.contents, 'PNG', (23, 23))

    def testPublishScaleWithInvalidUID(self):
        scale = self.view.scale('image', width=64, height=64)
        transaction.commit()
        # change the url so it's invalid...
        from zExceptions import NotFound
        with self.assertRaises(NotFound):
            self.browser.open(scale.url.replace('.png', 'x.png'))

    def testPublishScaleWithInvalidScale(self):
        scale = self.view.scale('image', 'no-such-scale')
        transaction.commit()
        self.assertEqual(scale, None)

    def test_getAvailableSizesWithInvalidScaleMethod(self):
        self.assertEqual(self.view.getAvailableSizes('no-such-scale'), {})

    def test_getAvailableSizesWithInvalidScaleProperty(self):
        self.assertEqual(self.view.available_sizes, {})

    def test_getImageSizeWithInvalidScale(self):
        self.assertEqual(self.view.getImageSize('no-such-scale'), (0, 0))

    def testGuardedAccess(self):
        # make sure it's not possible to access scales of forbidden images
        self.item.__allow_access_to_unprotected_subobjects__ = 0
        ImageScaling._sizes = {'foo': (23, 23)}
        transaction.commit()
        self.browser.addHeader(
            'Authorization',
            'Basic {0:s}:{1:s}'.format(TEST_USER_NAME, TEST_USER_PASSWORD)
        )
        from zExceptions import Unauthorized
        with self.assertRaises(Unauthorized):
            self.browser.open(
                self.layer['app'].absolute_url() + '/item/@@images/image/foo'
            )
        self.item.__allow_access_to_unprotected_subobjects__ = 1
class SyndicationControlPanelFunctionalTest(unittest.TestCase):

    layer = PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING

    def setUp(self):
        self.app = self.layer['app']
        self.portal = self.layer['portal']
        self.portal_url = self.portal.absolute_url()
        self.browser = Browser(self.app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization',
            'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)
        )

    def test_syndication_controlpanel_link(self):
        self.browser.open(
            "%s/@@overview-controlpanel" % self.portal_url)
        self.browser.getLink('Syndication').click()

    def test_syndication_controlpanel_backlink(self):
        self.browser.open(
            "%s/@@syndication-controlpanel" % self.portal_url)
        self.assertTrue("General" in self.browser.contents)

    def test_syndication_controlpanel_sidebar(self):
        self.browser.open(
            "%s/@@syndication-controlpanel" % self.portal_url)
        self.browser.getLink('Site Setup').click()
        self.assertTrue(
            self.browser.url.endswith('/plone/@@overview-controlpanel')
        )

    def test_syndication_controlpanel_view(self):
        view = getMultiAdapter((self.portal, self.portal.REQUEST),
                               name="syndication-controlpanel")
        self.assertTrue(view())

    def test_syndication_controlpanel_enabled(self):
        self.browser.open(
            "%s/@@syndication-controlpanel" % self.portal_url)
        self.browser.getControl(
            name='form.widgets.default_enabled:list').value = True
        self.browser.getControl(
            name='form.widgets.show_author_info:list').value = False
        self.browser.getControl(
            name='form.widgets.show_syndication_link:list').value = True
        self.browser.getControl('Save').click()

        self.assertTrue('Changes saved' in self.browser.contents)
        self.browser.open(
            "%s/@@syndication-controlpanel" % self.portal_url)

        self.assertEqual(
            self.browser.getControl(
                name='form.widgets.default_enabled:list'
            ).value,
            ['selected']
        )
        self.assertEqual(
            self.browser.getControl(
                name='form.widgets.show_author_info:list').value,
            []
        )
        self.assertEqual(
            self.browser.getControl(
                name='form.widgets.show_syndication_link:list'
            ).value,
            ['selected']
        )

    def test_create_collection(self):
        """Create collection and check if synPropertiesForm link is present.
        """
        # create collection
        self.portal.invokeFactory('Collection', 'collection')
        self.portal.collection.query = [
            {
                "i": "portal_type",
                "o": "plone.app.querystring.operation.selection.any",
                "v": ["News Item"]
            },
            {
                "i": "review_state",
                "o": "plone.app.querystring.operation.selection.any",
                "v": ["published"]
            }
        ]
        transaction.commit()
        # Enable syndication
        self.browser.open(
            "%s/@@syndication-controlpanel" % self.portal_url)
        self.browser.getControl(
            name='form.widgets.default_enabled:list').value = ['selected']
        self.browser.getControl(
            name='form.widgets.show_syndication_link:list'
        ).value = ['selected']
        self.browser.getControl('Save').click()
        self.assertTrue('Changes saved' in self.browser.contents)

        self.browser.open(self.portal_url + '/collection')
        self.assertTrue('/RSS' in self.browser.contents)
Esempio n. 42
0
class EditingControlPanelFunctionalTest(unittest.TestCase):
    """Test that changes in the editing control panel are actually
    stored in the registry.
    """

    layer = PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING

    def setUp(self):
        self.app = self.layer['app']
        self.request = self.layer['request']
        self.portal = self.layer['portal']
        self.portal_url = self.portal.absolute_url()

        registry = getUtility(IRegistry)
        self.settings = registry.forInterface(IEditingSchema, prefix='plone')

        self.browser = Browser(self.app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization',
            'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)
        )

    def test_editing_control_panel_link(self):
        self.browser.open(
            "%s/@@overview-controlpanel" % self.portal_url)
        self.browser.getLink('Editing').click()

    def test_editing_control_panel_backlink(self):
        self.browser.open(
            "%s/@@editing-controlpanel" % self.portal_url)
        self.assertTrue("Content" in self.browser.contents)

    def test_editing_control_panel_sidebar(self):
        self.browser.open(
            "%s/@@editing-controlpanel" % self.portal_url)
        self.browser.getLink('Site Setup').click()
        self.assertTrue(
            self.browser.url.endswith('/plone/@@overview-controlpanel')
        )

    @unittest.skip("TODO: Not implemented yet.")
    def test_visible_ids_active(self):
        pass

    def test_default_editor(self):
        self.browser.open(
            "%s/@@editing-controlpanel" % self.portal_url)
        self.browser.getControl("Default editor").value = ["None"]
        self.browser.getControl('Save').click()

        self.assertEqual(self.settings.default_editor, "None")

    @unittest.skip("TODO: Not implemented yet.")
    def test_default_editor_active(self):
        pass

    def test_available_editors_hidden(self):
        self.browser.open(
            "%s/@@editing-controlpanel" % self.portal_url)
        self.assertTrue('Available editors' not in self.browser.contents)

    def test_ext_editor(self):
        self.browser.open(
            "%s/@@editing-controlpanel" % self.portal_url)
        self.browser.getControl("Enable External Editor feature")\
            .selected = True
        self.browser.getControl('Save').click()

        self.assertEqual(self.settings.ext_editor, True)

    @unittest.skip("TODO: Not implemented yet.")
    def test_ext_editor_active(self):
        pass

    def test_enable_link_integrity_checks(self):
        self.browser.open(
            "%s/@@editing-controlpanel" % self.portal_url)
        self.browser.getControl("Enable link integrity checks")\
            .selected = True
        self.browser.getControl('Save').click()

        self.assertEqual(self.settings.enable_link_integrity_checks, True)

    def test_enable_link_integrity_checks_active(self):
        self.browser.open(
            "%s/@@editing-controlpanel" % self.portal_url)
        self.browser.getControl("Enable link integrity checks")\
            .selected = True
        self.browser.getControl('Save').click()
        self.assertTrue(linkintegrity_enabled())

    def test_lock_on_ttw_edit(self):
        self.browser.open(
            "%s/@@editing-controlpanel" % self.portal_url)
        self.browser.getControl("Enable locking for through-the-web edits")\
            .selected = True
        self.browser.getControl('Save').click()

        self.assertEqual(self.settings.lock_on_ttw_edit, True)

    @unittest.skip("TODO: Not implemented yet.")
    def test_lock_on_ttw_edit_active(self):
        pass
class MailControlPanelFunctionalTest(unittest.TestCase):
    """Test that changes in the mail control panel are actually
    stored in the registry.
    """

    layer = PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING

    def setUp(self):
        self.app = self.layer['app']
        self.portal = self.layer['portal']
        self.portal_url = self.portal.absolute_url()
        self.browser = Browser(self.app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization',
            'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)
        )

    def test_mail_controlpanel_link(self):
        self.browser.open(
            "%s/@@overview-controlpanel" % self.portal_url)
        self.browser.getLink('Mail').click()

    def test_mail_controlpanel_backlink(self):
        self.browser.open(
            "%s/@@mail-controlpanel" % self.portal_url)
        self.assertTrue("General" in self.browser.contents)

    def test_mail_controlpanel_sidebar(self):
        self.browser.open(
            "%s/@@mail-controlpanel" % self.portal_url)
        self.browser.getLink('Site Setup').click()
        self.assertTrue(
            self.browser.url.endswith('/plone/@@overview-controlpanel')
        )

    def test_mail_controlpanel_view(self):
        view = getMultiAdapter((self.portal, self.portal.REQUEST),
                               name="mail-controlpanel")
        self.assertTrue(view())

    def test_mail_controlpanel_smtp_host(self):
        self.browser.open(
            "%s/@@mail-controlpanel" % self.portal_url)
        self.browser.getControl(
            name='form.widgets.smtp_host').value = 'example.com'
        self.browser.getControl(
            name='form.widgets.email_from_name').value = 'John'
        self.browser.getControl(
            name='form.widgets.email_from_address').value = \
            '*****@*****.**'
        self.browser.getControl(name='form.buttons.save').click()

        registry = getUtility(IRegistry)
        settings = registry.forInterface(IMailSchema, prefix="plone")
        self.assertEqual(settings.smtp_host, 'example.com')

    def test_mail_controlpanel_smtp_port(self):
        self.browser.open(
            "%s/@@mail-controlpanel" % self.portal_url)
        self.browser.getControl(
            name='form.widgets.smtp_port').value = '88'
        self.browser.getControl(
            name='form.widgets.email_from_name').value = 'John'
        self.browser.getControl(
            name='form.widgets.email_from_address').value = \
            '*****@*****.**'
        self.browser.getControl(name='form.buttons.save').click()

        registry = getUtility(IRegistry)
        settings = registry.forInterface(IMailSchema, prefix="plone")
        self.assertEqual(str(settings.smtp_port), '88')

    def test_mail_controlpanel_smtp_userid(self):
        self.browser.open(
            "%s/@@mail-controlpanel" % self.portal_url)
        self.browser.getControl(
            name='form.widgets.smtp_userid').value = '*****@*****.**'
        self.browser.getControl(
            name='form.widgets.email_from_name').value = 'John'
        self.browser.getControl(
            name='form.widgets.email_from_address').value = \
            '*****@*****.**'
        self.browser.getControl(name='form.buttons.save').click()

        registry = getUtility(IRegistry)
        settings = registry.forInterface(IMailSchema, prefix="plone")
        self.assertEqual(settings.smtp_userid, '*****@*****.**')

    def test_mail_controlpanel_smtp_pass(self):
        self.browser.open(
            "%s/@@mail-controlpanel" % self.portal_url)
        self.browser.getControl(
            name='form.widgets.smtp_pass').value = 'secret'
        self.browser.getControl(
            name='form.widgets.email_from_name').value = 'John'
        self.browser.getControl(
            name='form.widgets.email_from_address').value = \
            '*****@*****.**'
        self.browser.getControl(name='form.buttons.save').click()

        registry = getUtility(IRegistry)
        settings = registry.forInterface(IMailSchema, prefix="plone")
        self.assertEqual(settings.smtp_pass, 'secret')

    def test_mail_controlpanel_smtp_pass_keep_on_saving(self):
        self.browser.open(
            "%s/@@mail-controlpanel" % self.portal_url)
        self.browser.getControl(
            name='form.widgets.smtp_userid').value = '*****@*****.**'
        self.browser.getControl(
            name='form.widgets.smtp_pass').value = 'secret'
        self.browser.getControl(
            name='form.widgets.email_from_name').value = 'John'
        self.browser.getControl(
            name='form.widgets.email_from_address').value = \
            '*****@*****.**'
        self.browser.getControl(name='form.buttons.save').click()
        self.browser.getControl(name='form.buttons.save').click()

        registry = getUtility(IRegistry)
        settings = registry.forInterface(IMailSchema, prefix="plone")
        self.assertEqual(settings.smtp_pass, 'secret')

    def test_mail_controlpanel_email_from_name(self):
        self.browser.open(
            "%s/@@mail-controlpanel" % self.portal_url)
        self.browser.getControl(
            name='form.widgets.email_from_name').value = 'John'
        self.browser.getControl(
            name='form.widgets.email_from_address').value = \
            '*****@*****.**'
        self.browser.getControl(name='form.buttons.save').click()

        registry = getUtility(IRegistry)
        settings = registry.forInterface(IMailSchema, prefix="plone")
        self.assertEqual(settings.email_from_name, 'John')

    def test_mail_controlpanel_email_from_address(self):
        self.browser.open(
            "%s/@@mail-controlpanel" % self.portal_url)
        self.browser.getControl(
            name='form.widgets.email_from_name').value = 'John'
        self.browser.getControl(
            name='form.widgets.email_from_address').value = \
            '*****@*****.**'
        self.browser.getControl(name='form.buttons.save').click()

        registry = getUtility(IRegistry)
        settings = registry.forInterface(IMailSchema, prefix="plone")
        self.assertEqual(settings.email_from_address, '*****@*****.**')

    def test_mail_controlpanel_contactinfo_page(self):
        self.browser.open(
            "%s/@@mail-controlpanel" % self.portal_url)
        self.browser.getControl(
            name='form.widgets.email_from_name').value = 'John'
        self.browser.getControl(
            name='form.widgets.email_from_address').value = \
            '*****@*****.**'
        self.browser.getControl(name='form.buttons.save').click()

        self.browser.open(
            "%s/contact-info" % self.portal_url)
        self.assertTrue(
            'Message' in self.browser.contents,
            u'Message exists not in the contact-info form!'
        )

    def test_controlpanel_overview_shows_no_unconfigured_mailhost_warning(
            self):
        self.browser.open(
            "%s/@@mail-controlpanel" % self.portal_url)
        self.browser.getControl(
            name='form.widgets.email_from_name').value = 'John'
        self.browser.getControl(
            name='form.widgets.email_from_address').value = \
            '*****@*****.**'
        self.browser.getControl(name='form.buttons.save').click()

        self.browser.open(
            "%s/overview-controlpanel" % self.portal_url)
        self.assertFalse(
            'not configured a mail host' in self.browser.contents,
            u'There should not be a warning for unconfigured mailhost!'
        )

    def test_controlpanel_overview_shows_unconfigured_mailhost_warning(
            self):
        registry = getUtility(IRegistry)
        settings = registry.forInterface(IMailSchema, prefix="plone")
        settings.email_from_name = None
        settings.email_from_address = None
        self.browser.open(
            "%s/overview-controlpanel" % self.portal_url)
        self.assertTrue(
            'not configured a mail host' in self.browser.contents,
            u'There should be a warning for unconfigured mailhost!'
        )
class TestSiteAdministratorRoleFunctional(unittest.TestCase):

    layer = PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING

    def _generateUsers(self):
        rtool = getToolByName(self.portal, 'portal_registration')
        rtool.addMember('DIispfuF', 'secret', ['Member'], [])
        rtool.addMember('siteadmin', 'secret', ['Site Administrator'], [])
        rtool.addMember('root', 'secret', ['Manager'], [])

    def setUp(self):
        self.app = self.layer['app']
        self.portal = self.layer['portal']
        self.request = self.layer['request']
        self.portal_url = self.portal.absolute_url()
        self.usergroups_url = "%s/@@usergroup-userprefs" % self.portal_url
        self.groups_url = "%s/@@usergroup-groupprefs" % self.portal_url
        self._generateUsers()
        setRoles(self.portal, TEST_USER_ID, ['Manager'])
        transaction.commit()

        self.browser = Browser(self.app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization',
            'Basic %s:%s' % (TEST_USER_ID, TEST_USER_PASSWORD,)
        )
        self.normal_user = '******'

    def _get_authenticator(self, browser=None):
        if not browser:
            browser = self.browser
        return browser.getControl(name='_authenticator').value

    def _simplify_white_space(self, text):
        """For easier testing we replace all white space with one space.

        And we remove white space around '<' and '>'.

        So this:

          <p
              id="foo"> Bar
          </p>

        becomes this:

          <p id="foo">Bar</p>
        """
        text = re.sub(r'\s*<\s*', '<', text)
        text = re.sub(r'\s*>\s*', '>', text)
        text = re.sub(r'\s+', ' ', text)
        return text

    def testControlPanelOverview(self):
        # make sure we can view the Site Setup page,
        # at both old and new URLs
        view = self.portal.restrictedTraverse('plone_control_panel')
        self.assertTrue(view())
        view = self.portal.restrictedTraverse('overview-controlpanel')
        self.assertTrue(view())

    def testUserManagerRoleCheckboxIsDisabledForNonManagers(self):
        login(self.portal, 'siteadmin')
        view = self.portal.restrictedTraverse('@@usergroup-userprefs')
        contents = view()
        self.assertTrue('<input type="checkbox" class="noborder" '
                        'name="users.roles:list:records" value="Manager" '
                        'disabled="disabled" />' in contents)

    def testManagerCanDelegateManagerRoleForUsers(self):
        # a user with the Manager role can grant the Manager role
        self.browser.addHeader(
            'Authorization',
            'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)
        )
        self.browser.open(self.usergroups_url)
        form = {
            '_authenticator': self._get_authenticator(),
            'users.id:records': self.normal_user,
            'users.roles:list:records': 'Manager',
            'form.button.Modify': 'Save',
            'form.submitted': 1,
        }
        post_data = urlencode(form)
        self.browser.post(self.usergroups_url, post_data)
        self.assertIn('Status: 200', str(self.browser.headers))

        roles = self.portal.acl_users.getUserById(self.normal_user).getRoles()
        self.assertEqual(['Manager', 'Authenticated'], roles)

    def testNonManagersCannotDelegateManagerRoleForUsers(self):
        # a user without the Manager role cannot delegate the Manager role
        self.browser.addHeader(
            'Authorization', 'Basic siteadmin:secret')
        self.browser.open(self.usergroups_url)
        form = {
            '_authenticator': self._get_authenticator(),
            'users.id:records': self.normal_user,
            'users.roles:list:records': 'Manager',
            'form.button.Modify': 'Save',
            'form.submitted': 1,
        }
        post_data = urlencode(form)
        with self.assertRaises(zExceptions.Forbidden):
            self.browser.post(self.usergroups_url, post_data)
        roles = self.portal.acl_users.getUserById(self.normal_user).getRoles()
        self.assertEqual(['Member', 'Authenticated'], roles)

    def testNonManagersCanEditOtherRolesOfUsersWithManagerRole(self):
        roles = self.portal.acl_users.getUserById('root').getRoles()
        self.assertEqual(['Manager', 'Authenticated'], roles)
        self.browser.addHeader(
            'Authorization', 'Basic siteadmin:secret')
        self.browser.open(self.usergroups_url)
        form = {
            '_authenticator': self._get_authenticator(),
            'users.id:records': 'root',
            'users.roles:list:records': ('Member', 'Manager'),
            'form.button.Modify': 'Save',
            'form.submitted': 1,
        }
        post_data = urlencode(form, doseq=True)
        self.browser.post(self.usergroups_url, post_data)
        roles = self.portal.acl_users.getUserById('root').getRoles()
        self.assertEqual(['Authenticated', 'Manager', 'Member'], sorted(roles))

    def testGroupManagerRoleCheckboxIsDisabledForNonManagers(self):
        self.browser.addHeader(
            'Authorization', 'Basic siteadmin:secret')
        self.browser.open(self.groups_url)
        contents = self._simplify_white_space(self.browser.contents)
        self.assertTrue('<input type="checkbox" class="noborder" '
                        'name="group_Reviewers:list" value="Manager" '
                        'disabled="disabled" />' in contents)

    def testManagerCanDelegateManagerRoleForGroups(self):
        # a user with the Manager role can grant the Manager role
        roles = self.portal.acl_users.getGroupById('Reviewers').getRoles()
        self.assertEqual(['Reviewer', 'Authenticated'], roles)
        self.browser.addHeader(
            'Authorization',
            'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)
        )
        self.browser.open(self.groups_url)
        form = {
            '_authenticator': self._get_authenticator(),
            'group_Reviewers:list': ('', 'Manager'),
            'form.button.Modify': 'Save',
            'form.submitted': 1,
        }
        post_data = urlencode(form, doseq=True)
        self.browser.post(self.groups_url, post_data)
        roles = self.portal.acl_users.getGroupById('Reviewers').getRoles()
        self.assertEqual(['Manager', 'Authenticated'], roles)

    def testNonManagersCannotDelegateManagerRoleForGroups(self):
        # a user without the Manager role cannot delegate the Manager role
        self.browser.addHeader(
            'Authorization', 'Basic siteadmin:secret')

        self.browser.open(self.groups_url)
        form = {
            '_authenticator': self._get_authenticator(),
            'group_Reviewers:list': ('', 'Manager'),
            'form.button.Modify': 'Save',
            'form.submitted': 1,
        }
        post_data = urlencode(form, doseq=True)
        with self.assertRaises(zExceptions.Forbidden):
            self.browser.post(self.groups_url, post_data)
        # self.assertEqual(403, res.status)
        roles = self.portal.acl_users.getGroupById('Reviewers').getRoles()
        self.assertEqual(['Reviewer', 'Authenticated'], roles)

    def testNonManagersCanEditOtherRolesOfGroupsWithManagerRole(self):
        self.browser.addHeader(
            'Authorization', 'Basic siteadmin:secret')

        roles = self.portal.acl_users.getUserById('root').getRoles()
        self.assertEqual(['Manager', 'Authenticated'], roles)
        self.browser.open(self.groups_url)
        form = {
            '_authenticator': self._get_authenticator(),
            'group_Administrators:list': ('', 'Member', 'Manager'),
            'form.button.Modify': 'Save',
            'form.submitted': 1,
        }
        post_data = urlencode(form, doseq=True)
        self.browser.post(self.groups_url, post_data)
        # self.assertEqual(200, res.status)
        roles = self.portal.acl_users.getGroupById('Administrators').getRoles()
        self.assertEqual(['Authenticated', 'Manager', 'Member'], sorted(roles))

    def test_usergroup_usermembership_blocks_escalation(self):
        self.browser.addHeader(
            'Authorization', 'Basic siteadmin:secret')

        # groups granting the Manager role shouldn't show as a valid option to
        # add
        self.browser.open(
            self.portal_url + '/@@usergroup-usermembership?userid=%s' % self.normal_user)
        contents = self._simplify_white_space(self.browser.contents)
        self.assertTrue(
            '<input type="checkbox" class="noborder" name="add:list" '
            'value="Administrators" disabled="disabled" />' in contents
        )

        # and should not be addable
        form = {
            '_authenticator': self._get_authenticator(),
            'add:list': 'Administrators',
            'form.submitted': 1,
        }
        post_data = urlencode(form)
        with self.assertRaises(zExceptions.Forbidden):
            self.browser.open(
                self.portal_url + '/@@usergroup-usermembership?userid=%s' % self.normal_user, post_data
            )
        # self.assertEqual(403, res.status)
        roles = self.portal.acl_users.getUserById(self.normal_user).getRoles()
        self.assertEqual(['Member', 'Authenticated'], roles)

    def test_usergroup_groupmembership_blocks_escalation(self):
        # should not show section to add users for groups granting the Manager
        # role
        self.browser.addHeader(
            'Authorization', 'Basic siteadmin:secret')

        self.browser.open(
            self.portal_url + '/@@usergroup-groupmembership?groupname=Administrators'
        )
        contents = self._simplify_white_space(self.browser.contents)
        self.assertFalse('Search for new group members' in contents)

        # and should not be addable if we try to force it
        form = {
            '_authenticator': self._get_authenticator(),
            'add:list': self.normal_user,
            'form.submitted': 1,
        }
        post_data = urlencode(form)
        with self.assertRaises(zExceptions.Forbidden):
            self.browser.post(
                self.portal_url + '/@@usergroup-groupmembership?groupname=Administrators', post_data
            )
        # self.assertEqual(403, res.status)
        roles = self.portal.acl_users.getUserById(self.normal_user).getRoles()
        self.assertEqual(['Member', 'Authenticated'], roles)

    def test_user_registration_form_blocks_escalation(self):
        # groups granting the Manager role should not be available for
        # selection
        self.browser.addHeader(
            'Authorization', 'Basic siteadmin:secret')
        self.browser.open(self.portal_url + '/@@new-user')
        contents = self._simplify_white_space(self.browser.contents)
        self.assertFalse(
            '<input class="label checkboxType" id="form.groups.0" '
            'name="form.groups" type="checkbox" value="Administrators '
            '(Administrators)" />' in contents
        )
        # and should not be getting that roles if we try to force it
        form = {
            '_authenticator': self._get_authenticator(),
            'form.widgets.username': '******',
            'form.widgets.email': '*****@*****.**',
            'form.widgets.password': '******',
            'form.widgets.password_ctl': 'secret',
            'form.widgets.groups:list': 'Administrators',
            'form.widgets.groups-empty-marker': '1',
            'form.buttons.register': 'Register',
        }
        post_data = urlencode(form)
        self.browser.post(self.portal_url + '/@@new-user', post_data)
        self.assertEqual(
            ['Member', 'Authenticated'],
            self.portal.acl_users.getUserById('newuser').getRoles())

    def test_users_overview_blocks_deleting_managers(self):
        # a user without the Manager role cannot delete a user with the
        # Manager role
        self.browser.addHeader(
            'Authorization', 'Basic siteadmin:secret')

        self.browser.open(self.usergroups_url)
        contents = self._simplify_white_space(self.browser.contents)
        self.assertTrue(
            '<input type="checkbox" class="noborder notify" '
            'name="delete:list" value="root" disabled="disabled" />'
            in contents)

        form = {
            '_authenticator': self._get_authenticator(),
            'users.id:records': 'root',
            'delete:list': 'root',
            'form.button.Modify': 'Save',
            'form.submitted': 1,
        }
        post_data = urlencode(form)
        with self.assertRaises(zExceptions.Forbidden):
            self.browser.post(self.usergroups_url, post_data)
        # self.assertEqual(403, res.status)
        user = self.portal.acl_users.getUserById('root')
        self.assertTrue(user is not None)

    def test_groups_overview_blocks_deleting_managers(self):
        # a user without the Manager role cannot delete a group with the
        # Manager role
        self.browser.addHeader(
            'Authorization', 'Basic siteadmin:secret')

        self.browser.open(self.groups_url)
        contents = self._simplify_white_space(self.browser.contents)
        self.assertTrue(
            '<input type="checkbox" class="noborder notify" '
            'name="delete:list" value="Administrators" disabled="disabled" />'
            in contents
        )

        form = {
            '_authenticator': self._get_authenticator(),
            'delete:list': 'Administrators',
            'form.button.Modify': 'Save',
            'form.submitted': 1,
        }
        post_data = urlencode(form)
        with self.assertRaises(zExceptions.Forbidden):
            self.browser.post(self.groups_url, post_data)
        # self.assertEqual(403, res.status)
        group = self.portal.acl_users.getGroupById('Administrators')
        self.assertTrue(group is not None)
class LanguageControlPanelFunctionalTest(unittest.TestCase):
    """Test that changes in the language control panel are actually
    stored in the registry.
    """

    layer = PRODUCTS_CMFPLONE_FUNCTIONAL_TESTING

    def setUp(self):
        self.app = self.layer['app']
        self.portal = self.layer['portal']
        self.portal_url = self.portal.absolute_url()
        self.browser = Browser(self.app)
        self.browser.handleErrors = False
        self.browser.addHeader(
            'Authorization',
            'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)
        )

    def _inject_available_languages_field(self, value):
        """The in-and-out widget does not work without javascript, therefore
           we have to inject some values in order to make saving the form work.
        """
        form = self.browser.getForm(id='LanguageControlPanel')
        name = 'form.widgets.available_languages:list'
        field = webtest.forms.Hidden(form._form, 'input', name, 0, value=value)
        form._form.field_order.append((name, field))
        self.browser.getControl('Save').click()

    def test_language_control_panel_link(self):
        self.browser.open(
            "%s/@@overview-controlpanel" % self.portal_url)
        self.browser.getLink('Language').click()
        self.assertTrue("Language Settings" in self.browser.contents)

    def test_language_control_panel_backlink(self):
        self.browser.open(
            "%s/@@language-controlpanel" % self.portal_url)
        self.assertTrue("General" in self.browser.contents)

    def test_language_control_panel_sidebar(self):
        self.browser.open(
            "%s/@@language-controlpanel" % self.portal_url)
        self.browser.getLink('Site Setup').click()
        self.assertTrue(
            self.browser.url.endswith('/plone/@@overview-controlpanel')
        )

    def test_language_controlpanel_view(self):
        view = getMultiAdapter((self.portal, self.portal.REQUEST),
                               name="language-controlpanel")
        self.assertTrue(view())

    def test_default_language(self):
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ILanguageSchema, prefix='plone')
        self.browser.open(
            "%s/@@language-controlpanel" % self.portal_url)
        self.assertEqual(settings.default_language, 'en')
        self.assertEqual(
            self.browser.getControl(
                'Site language'
            ).value,
            ['en']
        )
        self.browser.getControl(
            'Site language'
        ).value = ['de']
        self._inject_available_languages_field('en')
        self._inject_available_languages_field('de')
        self.browser.getControl(name='form.buttons.save').click()

        self.assertEqual(settings.default_language, 'de')

    # def test_available_languages(self):
    #     registry = getUtility(IRegistry)
    #     settings = registry.forInterface(ILanguageSchema, prefix='plone')
    #     self.browser.open(
    #         "%s/@@language-controlpanel" % self.portal_url)
    #     self.assertEqual(settings.available_languages, ['en'])
    #     self.assertEqual(
    #         self.browser.getControl(
    #             name='form.widgets.available_languages.to'
    #         ).options,
    #         ['en']
    #     )
    #     control = self.browser.getForm(index=1)
    #     self.in_out_select(
    #         control, 'form.widgets.available_languages:list', 'Deutsch')
    #     self.browser.getControl('Save').click()
    #     self.assertEqual(settings.available_languages, ['en', 'de'])

    def test_use_combined_language_codes(self):
        """This checks swithing combined languages codes support off/on."""
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ILanguageSchema, prefix='plone')
        self.browser.open(
            "%s/@@language-controlpanel" % self.portal_url)
        self.assertEqual(settings.use_combined_language_codes, True)
        self.assertEqual(
            self.browser.getControl(
                'Show country-specific language variants'
            ).selected,
            True
        )
        self.browser.getControl(
            'Show country-specific language variants'
        ).selected = False

        self._inject_available_languages_field('en')
        self.browser.getControl('Save').click()

        self.assertEqual(settings.use_combined_language_codes, False)

    def test_display_flags(self):
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ILanguageSchema, prefix='plone')
        self.browser.open(
            "%s/@@language-controlpanel" % self.portal_url)
        self.assertEqual(settings.display_flags, False)
        self.assertEqual(
            self.browser.getControl(
                'Show language flags'
            ).selected,
            False
        )
        self.browser.getControl(
            'Show language flags'
        ).selected = True

        self._inject_available_languages_field('en')
        self.browser.getControl('Save').click()

        self.assertEqual(settings.display_flags, True)

    def test_use_content_negotiation(self):
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ILanguageSchema, prefix='plone')
        self.browser.open(
            "%s/@@language-controlpanel" % self.portal_url)
        self.assertEqual(settings.use_content_negotiation, False)
        self.assertEqual(
            self.browser.getControl(
                'Use the language of the content item'
            ).selected,
            False
        )
        self.browser.getControl(
            'Use the language of the content item'
        ).selected = True

        self._inject_available_languages_field('en')
        self.browser.getControl('Save').click()

        self.assertEqual(settings.use_content_negotiation, True)

    def test_use_path_negotiation(self):
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ILanguageSchema, prefix='plone')
        self.browser.open(
            "%s/@@language-controlpanel" % self.portal_url)
        self.assertEqual(settings.use_path_negotiation, False)
        self.assertEqual(
            self.browser.getControl(
                'Use language codes in URL path for manual override'
            ).selected,
            False
        )
        self.browser.getControl(
            'Use language codes in URL path for manual override'
        ).selected = True

        self._inject_available_languages_field('en')
        self.browser.getControl('Save').click()

        self.assertEqual(settings.use_path_negotiation, True)

    def test_use_cookie_negotiation(self):
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ILanguageSchema, prefix='plone')
        self.browser.open(
            "%s/@@language-controlpanel" % self.portal_url)
        self.assertEqual(settings.use_cookie_negotiation, False)
        self.assertEqual(
            self.browser.getControl(
                'Use cookie for manual override'
            ).selected,
            False
        )
        self.browser.getControl(
            'Use cookie for manual override'
        ).selected = True

        self._inject_available_languages_field('en')
        self.browser.getControl('Save').click()

        self.assertEqual(settings.use_cookie_negotiation, True)

    def test_authenticated_users_only(self):
        control_label = "Authenticated users only"
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ILanguageSchema, prefix='plone')
        self.browser.open(
            "%s/@@language-controlpanel" % self.portal_url)
        self.assertEqual(settings.authenticated_users_only, False)
        self.assertEqual(
            self.browser.getControl(control_label).selected,
            False
        )
        self.browser.getControl(control_label).selected = True

        self._inject_available_languages_field('en')
        self.browser.getControl('Save').click()

        self.assertEqual(settings.authenticated_users_only, True)

    def test_set_cookie_always(self):
        control_label = "Set the language cookie always"
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ILanguageSchema, prefix='plone')
        self.browser.open(
            "%s/@@language-controlpanel" % self.portal_url)
        self.assertEqual(settings.set_cookie_always, False)
        self.assertEqual(
            self.browser.getControl(control_label).selected,
            False
        )
        self.browser.getControl(control_label).selected = True
        self._inject_available_languages_field('en')
        self.browser.getControl('Save').click()

        self.assertEqual(settings.set_cookie_always, True)

    def test_use_subdomain_negotiation(self):
        control_label = "Use subdomain"
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ILanguageSchema, prefix='plone')
        self.browser.open(
            "%s/@@language-controlpanel" % self.portal_url)
        self.assertEqual(settings.use_subdomain_negotiation, False)
        self.assertEqual(
            self.browser.getControl(control_label).selected,
            False
        )
        self.browser.getControl(control_label).selected = True
        self._inject_available_languages_field('en')
        self.browser.getControl('Save').click()

        self.assertEqual(settings.use_subdomain_negotiation, True)

    def test_use_cctld_negotiation(self):
        control_label = "Use top-level domain"
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ILanguageSchema, prefix='plone')
        self.browser.open(
            "%s/@@language-controlpanel" % self.portal_url)
        self.assertEqual(settings.use_cctld_negotiation, False)
        self.assertEqual(
            self.browser.getControl(control_label).selected,
            False
        )
        self.browser.getControl(control_label).selected = True
        self._inject_available_languages_field('en')
        self.browser.getControl('Save').click()

        self.assertEqual(settings.use_cctld_negotiation, True)

    def test_use_request_negotiation(self):
        control_label = "Use browser language request negotiation"
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ILanguageSchema, prefix='plone')
        self.browser.open(
            "%s/@@language-controlpanel" % self.portal_url)
        self.assertEqual(settings.use_request_negotiation, False)
        self.assertEqual(
            self.browser.getControl(control_label).selected,
            False
        )
        self.browser.getControl(control_label).selected = True
        self._inject_available_languages_field('en')
        self.browser.getControl('Save').click()

        self.assertEqual(settings.use_request_negotiation, True)