예제 #1
0
    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)
예제 #2
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
예제 #3
0
def get_feedback_messages(content):
    """Find and return the feedback messages of the page."""
    message_classes = [
        'message', 'informational message', 'error message', 'warning message'
    ]
    soup = BeautifulSoup(content,
                         parseOnlyThese=SoupStrainer(
                             ['div', 'p'], {'class': message_classes}))
    return [extract_text(tag) for tag in soup]
예제 #4
0
 def test_featured_projects_manage_link_requires_edit(self):
     self.setUpRegistryExpert()
     view = create_initialized_view(self.root,
                                    'index.html',
                                    principal=self.expert)
     # Stub out the getRecentBlogPosts which fetches a blog feed using
     # urlfetch.
     view.getRecentBlogPosts = lambda: []
     content = BeautifulSoup(view(), parse_only=SoupStrainer('a'))
     self.assertTrue(
         content.find('a', href='+featuredprojects'),
         "Cannot find the +featuredprojects link on the first page")
예제 #5
0
 def test_has_logo_without_watermark(self):
     root = getUtility(ILaunchpadRoot)
     user = self.factory.makePerson()
     login_person(user)
     view = create_initialized_view(root, 'index.html', principal=user)
     # Replace the blog posts so the view does not make a network request.
     view.getRecentBlogPosts = lambda: []
     markup = BeautifulSoup(view(), parse_only=SoupStrainer(id='document'))
     self.assertIs(False, view.has_watermark)
     self.assertIs(None, markup.find(True, id='watermark'))
     logo = markup.find(True, id='launchpad-logo-and-name')
     self.assertIsNot(None, logo)
     self.assertEqual('/@@/launchpad-logo-and-name.png', logo['src'])
예제 #6
0
    def test_blog_posts_with_memcache(self):
        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"),
        ]
        key = '%s:homepage-blog-posts' % config.instance_name
        getUtility(IMemcacheClient).set(key, posts)

        root = getUtility(ILaunchpadRoot)
        with anonymous_logged_in():
            view = create_initialized_view(root, 'index.html')
            result = view()
        markup = BeautifulSoup(
            result, parse_only=SoupStrainer(id='homepage-blogposts'))
        items = markup.findAll('li', 'news')
        self.assertEqual(3, len(items))
예제 #7
0
def find_tags_by_class(content, class_, only_first=False):
    """Find and return one or more tags matching the given class(es)"""

    match_classes = set(class_.split())

    def class_matcher(value):
        if value is None:
            return False
        classes = set(value.split())
        return match_classes.issubset(classes)

    soup = BeautifulSoup(
        content, parseOnlyThese=SoupStrainer(attrs={'class': class_matcher}))
    if only_first:
        find = BeautifulSoup.find
    else:
        find = BeautifulSoup.findAll
    return find(soup, attrs={'class': class_matcher})
예제 #8
0
def find_tag_by_id(content, id):
    """Find and return the tag with the given ID"""
    if isinstance(content, PageElement):
        elements_with_id = content.findAll(True, {'id': id})
    elif isinstance(content, PageElement4):
        elements_with_id = content.find_all(True, {'id': id})
    else:
        elements_with_id = [
            tag for tag in BeautifulSoup(content,
                                         parseOnlyThese=SoupStrainer(id=id))
        ]
    if len(elements_with_id) == 0:
        return None
    elif len(elements_with_id) == 1:
        return elements_with_id[0]
    else:
        raise DuplicateIdError('Found %d elements with id %r' %
                               (len(elements_with_id), id))
예제 #9
0
    def test_blog_disabled(self):
        """Launchpad blog not queried for display without feature"""
        calls = []

        def _get_blog_posts():
            calls.append('called')
            return []

        root = getUtility(ILaunchpadRoot)
        user = self.factory.makePerson()
        login_person(user)
        view = create_initialized_view(root, 'index.html', principal=user)
        view.getRecentBlogPosts = _get_blog_posts
        markup = BeautifulSoup(view(), parse_only=SoupStrainer(id='homepage'))
        self.assertEqual([], calls)
        self.assertIs(None, markup.find(True, id='homepage-blogposts'))
        # Even logged in users should get the launchpad intro text in the left
        # column rather than blank space when the blog is not being displayed.
        self.assertTrue(view.show_whatslaunchpad)
        self.assertTrue(markup.find(True, 'homepage-whatslaunchpad'))