Example #1
0
def print_upstream_linking_form(browser):
    """Print the upstream linking form found via +choose-affected-product.

    The resulting output will look something like:
    (*) A checked option
        [A related text field]
    ( ) An unchecked option
    """
    soup = BeautifulSoup(browser.contents)

    link_upstream_how_radio_control = browser.getControl(
        name='field.link_upstream_how')
    link_upstream_how_buttons = soup.findAll(
        'input', {'name': 'field.link_upstream_how'})

    wrapper = textwrap.TextWrapper(width=65, subsequent_indent='    ')
    for button in link_upstream_how_buttons:
        # Print the radio button.
        label = button.findParent('label')
        if label is None:
            label = soup.find('label', {'for': button['id']})
        if button.get('value') in link_upstream_how_radio_control.value:
            print wrapper.fill('(*) %s' % extract_text(label))
        else:
            print wrapper.fill('( ) %s' % extract_text(label))
        # Print related text field, if found. Assumes that the text
        # field is in the same table row as the radio button.
        text_field = button.findParent('tr').find('input', {'type': 'text'})
        if text_field is not None:
            text_control = browser.getControl(name=text_field.get('name'))
            print '    [%s]' % text_control.value.ljust(10)
    def test_does_display_child_diff(self):
        # If the child's latest published version is not the same as the base
        # version, we display two links to two diffs.
        changelog_lfa = self.factory.makeChangelog('foo',
                                                   ['0.1-1derived1', '0.1-1'])
        parent_changelog_lfa = self.factory.makeChangelog(
            'foo', ['0.1-2', '0.1-1'])
        transaction.commit()  # Yay, librarian.
        ds_diff = self.factory.makeDistroSeriesDifference(
            versions={
                'derived': '0.1-1derived1',
                'parent': '0.1-2',
            },
            changelogs={
                'derived': changelog_lfa,
                'parent': parent_changelog_lfa
            })

        self.assertEqual('0.1-1', ds_diff.base_version)
        with person_logged_in(self.factory.makePerson()):
            view = create_initialized_view(ds_diff,
                                           '+listing-distroseries-extra')
            soup = BeautifulSoup(view())
        tags = soup.find('ul', 'package-diff-status').findAll('span')
        self.assertEqual(2, len(tags))
Example #3
0
    def test_rendering(self):
        some_repo = self.factory.makeGitRepository(
            owner=self.owner, target=self.target, name="foo")
        self.factory.makeGitRefs(
            some_repo,
            paths=["refs/heads/master", "refs/heads/bug-1234"])

        other_repo = self.factory.makeGitRepository(
            owner=self.owner, target=self.target, name="bar")
        self.factory.makeGitRefs(other_repo, paths=["refs/heads/bug-2468"])

        view = create_initialized_view(self.context, '+git')
        self.assertIs(None, view.default_git_repository)

        content = view()
        soup = BeautifulSoup(content)

        # No details about the default repo are shown, as a person
        # without a target doesn't have a default repo
        self.assertNotIn('Branches', content)
        self.assertNotIn('Browse the code', content)
        self.assertNotIn('git clone', content)
        self.assertNotIn('bug-1234', content)

        # All owned repos are listed.
        table = soup.find(
            'div', id='gitrepositories-table-listing').find('table')
        self.assertContentEqual(
            [some_repo.git_identity, other_repo.git_identity],
            [link.find(text=True) for link in table.findAll('a')])
Example #4
0
 def test_sharing_menu(self):
     url = canonical_url(self.pillar)
     sharing_url = canonical_url(self.pillar, view_name='+sharing')
     browser = setupBrowserForUser(user=self.driver)
     browser.open(url)
     soup = BeautifulSoup(browser.contents)
     sharing_menu = soup.find('a', {'href': sharing_url})
     self.assertIsNotNone(sharing_menu)
 def contains_one_link_to_diff(self, html_or_soup, package_diff):
     """Return whether the html contains a link to the diff content."""
     if not (isinstance(html_or_soup, BeautifulSoup)):
         soup = BeautifulSoup(html_or_soup)
     else:
         soup = html_or_soup
     return 1 == len(
         soup.findAll('a', href=package_diff.diff_content.http_url))
 def number_of_request_diff_texts(self, html_or_soup):
     """Returns the number of request diff text."""
     if not (isinstance(html_or_soup, BeautifulSoup)):
         soup = BeautifulSoup(html_or_soup)
     else:
         soup = html_or_soup
     class_dict = {'class': re.compile('request-derived-diff')}
     return len(soup.findAll('span', class_dict))
Example #7
0
 def test_product_with_edit_permission(self):
     login_person(self.product.owner)
     self.view = create_initialized_view(
         self.product, '+questions', principal=self.product.owner)
     content = BeautifulSoup(self.view())
     self.assertCommonPageElements(content)
     self.assertTrue(
         content.find(True, id='configure-support') is not None)
Example #8
0
 def test_call(self):
     # The __call__ method sets up the widgets and the options.
     markup = self.widget()
     self.assertIsNotNone(self.widget.person_widget)
     self.assertIn("repository_owner", self.widget.options)
     self.assertIn("person", self.widget.options)
     soup = BeautifulSoup(markup)
     fields = soup.findAll(["input", "select"], {"id": re.compile(".*")})
     ids = [field["id"] for field in fields]
     self.assertContentEqual(self.expected_ids, ids)
 def test_call(self):
     # The __call__ method sets up the widgets.
     markup = self.widget()
     self.assertIsNotNone(self.widget.repository_widget)
     self.assertIsNotNone(self.widget.path_widget)
     soup = BeautifulSoup(markup)
     fields = soup.findAll("input", id=True)
     ids = [field["id"] for field in fields]
     self.assertContentEqual(
         ["field.git_ref.repository", "field.git_ref.path"], ids)
Example #10
0
    def get_text_values(self, bug):
        """Returns the text of status and substatus for the given bug.

        This is done by downloading the HTML bug page and scraping it.
        """
        url = '%s%s' % (self.base_url, bug['id'])
        page = self.fetch(url).read()
        soup = BeautifulSoup(page)
        return tuple(
            node.string for node in
            soup.find('th', text='Status').findNext('td').findAll('span'))
 def test_filebug_information_type_public_policy(self):
     # The vocabulary for information_type when filing a bug is created
     # correctly for non commercial projects.
     product = self.factory.makeProduct(official_malone=True)
     with person_logged_in(product.owner):
         view = create_initialized_view(product,
                                        '+filebug',
                                        principal=product.owner)
         html = view.render()
         soup = BeautifulSoup(html)
     self.assertIsNone(soup.find('label', text="Proprietary"))
Example #12
0
 def test_view_contents(self):
     # Distributions are rendered with the correct text.
     url = canonical_url(self.pillar, view_name='+sharing')
     browser = setupBrowserForUser(user=self.driver)
     browser.open(url)
     soup = BeautifulSoup(browser.contents)
     commercial_text = soup.find('p', {'id': 'commercial-project-text'})
     non_commercial_text = soup.find(
         'p', {'id': 'non-commercial-project-text'})
     self.assertIsNone(commercial_text)
     self.assertIsNone(non_commercial_text)
    def test_blacklist_options_disabled(self):
        # Blacklist options are disabled to the users who are *not* archive
        # admins.
        ds_diff = self.factory.makeDistroSeriesDifference()
        person = self.factory.makePerson()
        view_content = self.getViewContentXmlHttpRequest(
            ds_diff, '+listing-distroseries-extra', person)
        soup = BeautifulSoup(view_content)

        self.assertEqual(
            1, len(soup.findAll('div',
                                {'class': 'blacklist-options-disabled'})))
 def test_filebug_information_type_vocabulary(self):
     # The vocabulary for information_type when filing a bug is created
     # correctly.
     product = self.factory.makeProduct(official_malone=True)
     with person_logged_in(product.owner):
         view = create_initialized_view(product,
                                        '+filebug',
                                        principal=product.owner)
         html = view.render()
         soup = BeautifulSoup(html)
     for info_type in product.getAllowedBugInformationTypes():
         self.assertIsNotNone(soup.find('label', text=info_type.title))
Example #15
0
 def test_view_contents_commercial_project(self):
     # Commercial projects are rendered with the correct text.
     self.factory.makeCommercialSubscription(self.pillar)
     url = canonical_url(self.pillar, view_name='+sharing')
     browser = setupBrowserForUser(user=self.driver)
     browser.open(url)
     soup = BeautifulSoup(browser.contents)
     commercial_text = soup.find('p', {'id': 'commercial-project-text'})
     non_commercial_text = soup.find(
         'p', {'id': 'non-commercial-project-text'})
     self.assertIsNotNone(commercial_text)
     self.assertIsNone(non_commercial_text)
    def test_blacklist_options(self):
        # Blacklist options are presented to the users who are archive
        # admins.
        ds_diff = self.factory.makeDistroSeriesDifference()
        archive_admin = self.factory.makeArchiveAdmin(
            archive=ds_diff.derived_series.main_archive)
        view_content = self.getViewContentXmlHttpRequest(
            ds_diff, '+listing-distroseries-extra', archive_admin)
        soup = BeautifulSoup(view_content)

        self.assertEqual(
            1, len(soup.findAll('div', {'class': 'blacklist-options'})))
 def test_filebug_information_type_proprietary_policy(self):
     # The vocabulary for information_type when filing a bug is created
     # correctly for a project with a proprietary sharing policy.
     product = self.factory.makeProduct(official_malone=True)
     self.factory.makeCommercialSubscription(product=product)
     with person_logged_in(product.owner):
         product.setBugSharingPolicy(BugSharingPolicy.PROPRIETARY)
         view = create_initialized_view(product,
                                        '+filebug',
                                        principal=product.owner)
         html = view.render()
         soup = BeautifulSoup(html)
     self.assertIsNotNone(soup.find('label', text="Proprietary"))
 def test_filebug_view_renders_info_type_widget(self):
     # The info type widget is rendered for bug supervisor roles.
     product = self.factory.makeProduct(official_malone=True)
     with person_logged_in(product.owner):
         view = create_initialized_view(product,
                                        '+filebug',
                                        principal=product.owner)
         html = view.render()
         soup = BeautifulSoup(html)
     self.assertIsNone(
         soup.find('input', attrs={'name': 'field.security_related'}))
     self.assertIsNotNone(
         soup.find('input', attrs={'name': 'field.information_type'}))
Example #19
0
 def test_call(self):
     # The __call__ method sets up the widgets.
     markup = self.widget()
     self.assertIsNotNone(self.widget.core_widget)
     self.assertIsNotNone(self.widget.snapcraft_widget)
     soup = BeautifulSoup(markup)
     fields = soup.findAll(["input"], {"id": re.compile(".*")})
     expected_ids = [
         "field.auto_build_channels.core",
         "field.auto_build_channels.snapcraft",
         ]
     ids = [field["id"] for field in fields]
     self.assertContentEqual(expected_ids, ids)
Example #20
0
 def test_call(self):
     # The __call__ method sets up the widgets.
     markup = self.widget()
     self.assertIsNotNone(self.widget.track_widget)
     self.assertIsNotNone(self.widget.risks_widget)
     soup = BeautifulSoup(markup)
     fields = soup.findAll(["input"], {"id": re.compile(".*")})
     expected_ids = [
         "field.channels.risks.%d" % i for i in range(len(self.risks))
     ]
     expected_ids.append("field.channels.track")
     expected_ids.append("field.channels.branch")
     ids = [field["id"] for field in fields]
     self.assertContentEqual(expected_ids, ids)
 def test_filebug_view_renders_security_related(self):
     # The security_related checkbox is rendered for non bug supervisors.
     product = self.factory.makeProduct(official_malone=True)
     anyone = self.factory.makePerson()
     with person_logged_in(anyone):
         view = create_initialized_view(product,
                                        '+filebug',
                                        principal=anyone)
         html = view.render()
         soup = BeautifulSoup(html)
     self.assertIsNotNone(
         soup.find('input', attrs={'name': 'field.security_related'}))
     self.assertIsNone(
         soup.find('input', attrs={'name': 'field.information_type'}))
Example #22
0
 def test_anonymous_view_specification_with_private_subscriber(self):
     # A specification with a private subscriber is not rendered for anon.
     private_subscriber = self.factory.makeTeam(
         name="privateteam", visibility=PersonVisibility.PRIVATE)
     spec = self.factory.makeSpecification()
     with person_logged_in(spec.owner):
         spec.subscribe(private_subscriber, spec.owner)
         # Viewing the specification doesn't display private subscriber.
         url = canonical_url(spec, rootsite='blueprints')
         browser = self._getBrowser()
         browser.open(url)
         soup = BeautifulSoup(browser.contents)
         self.assertIsNone(
             soup.find('div', attrs={'id': 'subscriber-privateteam'}))
 def test_call(self):
     # The __call__ method setups the widgets and the options.
     markup = self.widget()
     self.assertIsNot(None, self.widget.product_widget)
     self.assertTrue('personal' in self.widget.options)
     expected_ids = [
         'field.target.option.personal',
         'field.target.option.product',
         'field.target.product',
     ]
     soup = BeautifulSoup(markup)
     fields = soup.findAll(['input', 'select'], {'id': re.compile('.*')})
     ids = [field['id'] for field in fields]
     self.assertContentEqual(expected_ids, ids)
Example #24
0
 def test_call(self):
     # The __call__ method sets up the widgets and the options.
     markup = self.widget()
     self.assertIsNotNone(self.widget.ppa_widget)
     self.assertIn("primary", self.widget.options)
     self.assertIn("ppa", self.widget.options)
     soup = BeautifulSoup(markup)
     fields = soup.findAll(["input", "select"], {"id": re.compile(".*")})
     expected_ids = [
         "field.archive.option.primary",
         "field.archive.option.ppa",
         "field.archive.ppa",
     ]
     ids = [field["id"] for field in fields]
     self.assertContentEqual(expected_ids, ids)
    def test_comments_rendered(self):
        # If there are comments on the difference, they are rendered.
        ds_diff = self.factory.makeDistroSeriesDifference()
        person = self.factory.makePerson()
        with person_logged_in(person):
            ds_diff.addComment(person, "I'm working on this.")
            ds_diff.addComment(person, "Here's another comment.")

        view = create_initialized_view(ds_diff, '+listing-distroseries-extra')
        soup = BeautifulSoup(view())

        self.assertEqual(
            1, len(soup.findAll('pre', text="I'm working on this.")))
        self.assertEqual(
            1, len(soup.findAll('pre', text="Here's another comment.")))
Example #26
0
 def test_remove_link_not_shown_if_no_duplicate(self):
     with person_logged_in(self.bug_owner):
         view = create_initialized_view(self.bug.default_bugtask,
                                        name="+duplicate",
                                        principal=self.bug_owner)
         soup = BeautifulSoup(view.render())
     self.assertIsNone(soup.find(attrs={'id': 'field.actions.remove'}))
Example #27
0
    def test_ajax_remove_duplicate(self):
        # An ajax request to remove a duplicate returns the new bugtask table.
        with person_logged_in(self.bug_owner):
            self.bug.markAsDuplicate(self.duplicate_bug)
            extra = {
                'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest',
            }
            form = {
                'field.actions.remove': u'Remove Duplicate',
            }

            view = create_initialized_view(self.bug.default_bugtask,
                                           name="+duplicate",
                                           principal=self.bug_owner,
                                           form=form,
                                           **extra)
            result_html = view.render()

        self.assertIsNone(self.bug.duplicateof)
        self.assertEqual(view.request.response.getHeader('content-type'),
                         'text/html')
        soup = BeautifulSoup(result_html)
        table = soup.find('table', {
            'id': 'affected-software',
            'class': 'listing'
        })
        self.assertIsNotNone(table)
    def test_blog_posts(self):
        """Posts from the launchpad blog are shown when feature is enabled"""
        self.useFixture(FeatureFixture({'app.root_blog.enabled': True}))
        posts = [
            self._make_blog_post(1, "A post", "Post contents.", "2002"),
            self._make_blog_post(2, "Another post", "More contents.", "2003"),
        ]
        calls = []

        def _get_blog_posts():
            calls.append('called')
            return posts

        root = getUtility(ILaunchpadRoot)
        with anonymous_logged_in():
            view = create_initialized_view(root, 'index.html')
            view.getRecentBlogPosts = _get_blog_posts
            result = view()
        markup = BeautifulSoup(
            result, parse_only=SoupStrainer(id='homepage-blogposts'))
        self.assertEqual(['called'], calls)
        items = markup.findAll('li', 'news')
        # Notice about launchpad being opened is always added at the end
        self.assertEqual(3, len(items))
        a = items[-1].find("a")
        self.assertEqual("Launchpad now open source", a.string.strip())
        for post, item in zip(posts, items):
            a = item.find("a")
            self.assertEqual(post['link'], a["href"])
            self.assertEqual(post['title'], a.string)
Example #29
0
 def test_job_notifications_display_multiple(self):
     job1 = self.makeJob('package_1')
     job2 = self.makeJob('package_2', failed=True)
     job3 = self.makeJob('package_3')
     with person_logged_in(self.archive.owner):
         view = create_initialized_view(self.archive,
                                        "+packages",
                                        principal=self.archive.owner)
         html = view.render()
     packages_matches = soupmatchers.HTMLContains(
         soupmatchers.Tag('job1',
                          'div',
                          attrs={
                              'class': 'pending-job',
                              'job_id': job1.id
                          }),
         soupmatchers.Tag('job2',
                          'div',
                          attrs={
                              'class': 'pending-job',
                              'job_id': job2.id
                          }),
         soupmatchers.Tag('job3',
                          'div',
                          attrs={
                              'class': 'pending-job',
                              'job_id': job3.id
                          }),
     )
     self.assertThat(html, packages_matches)
     self.assertEqual([],
                      BeautifulSoup(html).findAll(
                          'span', text=re.compile('Showing 5 of .')))
Example #30
0
    def getRemoteBug(self, bug_id):
        """See `ExternalBugTracker`."""
        # Only parse tables to save time and memory. If we didn't have
        # to check for application errors in the page (using
        # _checkForApplicationError) then we could be much more
        # specific than this.
        bug_page = BeautifulSoup(self._getPage('view.php?id=%s' %
                                               bug_id).content,
                                 convertEntities=BeautifulSoup.HTML_ENTITIES,
                                 parseOnlyThese=SoupStrainer('table'))

        app_error = self._checkForApplicationError(bug_page)
        if app_error:
            app_error_code, app_error_message = app_error
            # 1100 is ERROR_BUG_NOT_FOUND in Mantis (see
            # mantisbt/core/constant_inc.php).
            if app_error_code == '1100':
                return None, None
            else:
                raise BugWatchUpdateError("Mantis APPLICATION ERROR #%s: %s" %
                                          (app_error_code, app_error_message))

        bug = {
            'id': bug_id,
            'status': self._findValueRightOfKey(bug_page, 'Status'),
            'resolution': self._findValueRightOfKey(bug_page, 'Resolution')
        }

        return int(bug_id), bug