← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~wgrant/launchpad/better-breadcrumbery into lp:launchpad

 

William Grant has proposed merging lp:~wgrant/launchpad/better-breadcrumbery into lp:launchpad.

Requested reviews:
  William Grant (wgrant): code

For more details, see:
https://code.launchpad.net/~wgrant/launchpad/better-breadcrumbery/+merge/243009
-- 
Your team Launchpad code reviewers is subscribed to branch lp:launchpad.
=== modified file 'lib/canonical/launchpad/icing/css/layout.css'
--- lib/canonical/launchpad/icing/css/layout.css	2014-11-27 00:45:34 +0000
+++ lib/canonical/launchpad/icing/css/layout.css	2014-11-27 07:55:25 +0000
@@ -87,18 +87,20 @@
     display: block;
     margin: 0 1em 0 0;
     }
-div.watermark-apps-portlet h1, div.watermark-apps-portlet h2 {
+#watermark-heading {
     color: #000;
-    font-weight: bold;
-    font-size: 30px;
-    line-height: 30px;
-    margin: 0;
-    }
-div.watermark-apps-portlet h2.secondary {
     font-weight: normal;
     font-size: 20px;
     line-height: 26px;
-    }
+    margin: 0;
+    }
+#watermark-heading :first-child {
+    font-size: 32px;
+    line-height: 32px;
+    }
+#watermark-heading :link, #watermark-heading :visited {
+    color: #000;
+}
 .watermark-apps-portlet ul.facetmenu {
     margin-top: 12px;
     margin-left: -0.5em;

=== modified file 'lib/lp/app/browser/launchpad.py'
--- lib/lp/app/browser/launchpad.py	2014-11-27 06:21:37 +0000
+++ lib/lp/app/browser/launchpad.py	2014-11-27 07:55:25 +0000
@@ -43,6 +43,7 @@
     )
 from zope.i18nmessageid import Message
 from zope.interface import (
+    alsoProvides,
     implements,
     Interface,
     )
@@ -167,6 +168,10 @@
 from lp.translations.interfaces.translations import IRosettaApplication
 
 
+class IFacetBreadcrumb(Interface):
+    pass
+
+
 class NavigationMenuTabs(LaunchpadView):
     """View class that helps its template render the navigation menu tabs.
 
@@ -253,7 +258,7 @@
 
 
 class Hierarchy(LaunchpadView):
-    """The hierarchy part of the location bar on each page."""
+    """The heading, title, facet links and breadcrumbs parts of each page."""
 
     @property
     def objects(self):
@@ -304,11 +309,11 @@
             # after it.
             for idx, breadcrumb in reversed(list(enumerate(breadcrumbs))):
                 if IMultiFacetedBreadcrumb.providedBy(breadcrumb):
-                    breadcrumbs.insert(
-                        idx + 1,
-                        Breadcrumb(
-                            breadcrumb.context, rootsite=facet.rootsite,
-                            text=facet.text))
+                    facet_crumb = Breadcrumb(
+                        breadcrumb.context, rootsite=facet.rootsite,
+                        text=facet.text)
+                    alsoProvides(facet_crumb, IFacetBreadcrumb)
+                    breadcrumbs.insert(idx + 1, facet_crumb)
                     # Ensure that all remaining breadcrumbs are
                     # themselves faceted.
                     for remaining_crumb in breadcrumbs[idx + 1:]:
@@ -321,6 +326,24 @@
         return breadcrumbs
 
     @property
+    def items_for_body(self):
+        """Return breadcrumbs to display in the page body's hierarchy section.
+
+        While the entire sequence of breadcrumbs must be included in the
+        document title, the first 0-3 are represented specially in the header
+        (headings and facet links), so we don't want to duplicate them in the
+        main content.
+        """
+        crumbs = []
+        for crumb in self.items:
+            if (IHeadingBreadcrumb.providedBy(crumb)
+                    or IFacetBreadcrumb.providedBy(crumb)):
+                crumbs = []
+                continue
+            crumbs.append(crumb)
+        return crumbs
+
+    @property
     def _naked_context_view(self):
         """Return the unproxied view for the context of the hierarchy."""
         # XXX wgrant 2014-11-16: Should just be able to use self.context
@@ -369,7 +392,7 @@
         # to display breadcrumbs either.
         has_major_heading = IMajorHeadingView.providedBy(
             self._naked_context_view)
-        return len(self.items) > 1 and not has_major_heading
+        return len(self.items_for_body) > 1 and not has_major_heading
 
     @property
     def heading_breadcrumbs(self):
@@ -380,29 +403,26 @@
         return crumbs
 
     def heading(self):
-        """Return the heading text for the page.
+        """Return the heading markup for the page.
 
-        If the context provides `IHeadingContext` then we return an
+        If the context provides `IMajorHeadingView` then we return an
         H1, else an H2.
         """
-        # The title is static, but only the context's index view gets an H1.
-        heading = 'h1' if IMajorHeadingView.providedBy(self.context) else 'h2'
+        # The title is static, but only the index view gets an H1.
+        tag = 'h1' if IMajorHeadingView.providedBy(self.context) else 'h2'
         # If there is actually no root context, then it's a top-level
         # context-less page so Launchpad.net is shown as the branding.
-        crumbs = self.heading_breadcrumbs
-        if len(crumbs) >= 1:
-            title = crumbs[0].detail
-        else:
-            title = 'Launchpad.net'
-        # For non-editable titles, generate the static heading.
-        markup = structured(
-            "<%(heading)s>%(title)s</%(heading)s>",
-            heading=heading, title=title).escapedtext
-        if len(crumbs) >= 2:
-            markup += structured(
-                '\n<%(heading)s class="secondary">%(title)s</%(heading)s>',
-                heading=heading, title=crumbs[1].detail).escapedtext
-        return markup
+        crumb_markups = []
+        for crumb in self.heading_breadcrumbs:
+            crumb_markups.append(
+                structured('<a href="%s">%s</a>', crumb.url, crumb.detail))
+        if not crumb_markups:
+            crumb_markups.append('Launchpad.net')
+        content = structured(
+            '<br />'.join(['%s'] * len(crumb_markups)), *crumb_markups)
+        return structured(
+            '<%s id="watermark-heading">%s</%s>',
+            tag, content, tag).escapedtext
 
     def logo(self):
         """Return the logo image for the top header breadcrumb's context."""

=== modified file 'lib/lp/app/browser/tales.py'
--- lib/lp/app/browser/tales.py	2014-11-25 20:28:05 +0000
+++ lib/lp/app/browser/tales.py	2014-11-27 07:55:25 +0000
@@ -81,7 +81,6 @@
     IContextMenu,
     IFacetMenu,
     ILaunchBag,
-    ILaunchpadRoot,
     INavigationMenu,
     NoCanonicalUrl,
     )
@@ -690,7 +689,7 @@
         """The page title to be used.
 
         By default, reverse breadcrumbs are always used if they are available.
-        If not available, then the view's .page_title attribut is used.
+        If not available, then the view's .page_title attribute is used.
         """
         ROOT_TITLE = 'Launchpad'
         view = self._context
@@ -698,7 +697,7 @@
         hierarchy_view = getMultiAdapter((view, request), name='+hierarchy')
         if (isinstance(view, SystemErrorView) or
             hierarchy_view is None or
-            not hierarchy_view.display_breadcrumbs):
+            len(hierarchy_view.items) < 2):
             # The breadcrumbs are either not available or are overridden.  If
             # the view has a .page_title attribute use that.
             page_title = getattr(view, 'page_title', None)

=== modified file 'lib/lp/app/templates/launchpad-hierarchy.pt'
--- lib/lp/app/templates/launchpad-hierarchy.pt	2011-11-19 04:58:54 +0000
+++ lib/lp/app/templates/launchpad-hierarchy.pt	2014-11-27 07:55:25 +0000
@@ -7,7 +7,7 @@
   i18n:domain="launchpad"
   tal:condition="view/display_breadcrumbs">
 
-<tal:breadcrumbs repeat="breadcrumb view/items">
+<tal:breadcrumbs repeat="breadcrumb view/items_for_body">
   <li>
     <a tal:attributes="href breadcrumb/url"
       tal:omit-tag="repeat/breadcrumb/end"><tal:text

=== modified file 'lib/lp/blueprints/stories/sprints/xx-sprints.txt'
--- lib/lp/blueprints/stories/sprints/xx-sprints.txt	2014-02-19 02:11:16 +0000
+++ lib/lp/blueprints/stories/sprints/xx-sprints.txt	2014-11-27 07:55:25 +0000
@@ -166,7 +166,7 @@
 
     >>> anon_browser.open('http://launchpad.dev/sprints/ubz')
     >>> print anon_browser.title
-    Ubuntu Below Zero (sprint or meeting)
+    Ubuntu Below Zero : Meetings
 
     >>> anon_browser.getLink('Change details')
     Traceback (most recent call last):
@@ -179,7 +179,7 @@
 
     >>> browser.open('http://launchpad.dev/sprints/ubz')
     >>> print browser.title
-    Ubuntu Below Zero (sprint or meeting)
+    Ubuntu Below Zero : Meetings
 
     >>> address = 'Holiday Inn Select, Downtown Montreal, Canada'
     >>> address in browser.contents

=== modified file 'lib/lp/blueprints/stories/standalone/xx-overview.txt'
--- lib/lp/blueprints/stories/standalone/xx-overview.txt	2014-11-26 23:50:26 +0000
+++ lib/lp/blueprints/stories/standalone/xx-overview.txt	2014-11-27 07:55:25 +0000
@@ -54,7 +54,6 @@
     >>> main = find_main_content(user_browser.contents)
     >>> print extract_text(main).encode('ascii', 'backslashreplace')
     Blueprints for 1.0
-    ...
     Launchpad lets projects track the features they intend to implement...
 
 Let's target an existing Mozilla Firefox blueprint to the 1.0 series:
@@ -68,8 +67,6 @@
     >>> main = find_main_content(browser.contents)
     >>> print extract_text(main).encode('ascii', 'backslashreplace')
     Target to a product series
-    Mozilla Firefox
-    ...
     Support Native SVG Objects
     ...
 
@@ -154,7 +151,6 @@
     >>> main = find_main_content(user_browser.contents)
     >>> print extract_text(main).encode('ascii', 'backslashreplace')
     Blueprints for Grumpy
-    ...
     Launchpad lets projects track the features they intend to implement...
 
 Let's target an existing Ubuntu blueprint to the Grumpy series:
@@ -169,8 +165,6 @@
     >>> main = find_main_content(browser.contents)
     >>> print extract_text(main).encode('ascii', 'backslashreplace')
     Target to a distribution series
-    Ubuntu
-    ...
     CD Media Integrity Check
     ...
     >>> series = browser.getControl('Series Goal')

=== modified file 'lib/lp/bugs/stories/bug-release-management/nomination-navigation.txt'
--- lib/lp/bugs/stories/bug-release-management/nomination-navigation.txt	2014-11-25 07:56:07 +0000
+++ lib/lp/bugs/stories/bug-release-management/nomination-navigation.txt	2014-11-27 07:55:25 +0000
@@ -11,7 +11,7 @@
     ... 'http://bugs.launchpad.dev/ubuntu/+source/mozilla-firefox/+bug/1'
     ... '/nominations/2/+editstatus')
     >>> print_location(admin_browser.contents)
-    Hierarchy: Ubuntu > ?mozilla-firefox? package > Bugs > Bug #1...
+    Hierarchy: Ubuntu Linux > ?mozilla-firefox? package > Bug #1...
     Tabs:
     * Overview - http://launchpad.dev/ubuntu/+source/mozilla-firefox
     * Code - http://code.launchpad.dev/ubuntu/+source/mozilla-firefox

=== modified file 'lib/lp/bugs/stories/bugs/xx-bug-activity.txt'
--- lib/lp/bugs/stories/bugs/xx-bug-activity.txt	2014-11-25 07:56:07 +0000
+++ lib/lp/bugs/stories/bugs/xx-bug-activity.txt	2014-11-27 07:55:25 +0000
@@ -12,7 +12,7 @@
 the main heading repeats the bug number for clarity:
 
     >>> print_location(anon_browser.contents)
-    Hierarchy: Debian > ?mozilla-firefox? package > Bugs > Bug #3...
+    Hierarchy: Debian GNU/Linux > ?mozilla-firefox? package > Bug #3...
     Tabs:
     * Overview - http://launchpad.dev/debian/+source/mozilla-firefox
     * Code - http://code.launchpad.dev/debian/+source/mozilla-firefox

=== modified file 'lib/lp/bugs/stories/bugs/xx-bug-contacts-reports.txt'
--- lib/lp/bugs/stories/bugs/xx-bug-contacts-reports.txt	2014-02-19 02:11:16 +0000
+++ lib/lp/bugs/stories/bugs/xx-bug-contacts-reports.txt	2014-11-27 07:55:25 +0000
@@ -3,8 +3,7 @@
 
     >>> anon_browser.open("http://launchpad.dev/~name16/+packagebugs";)
     >>> print extract_text(find_main_content(anon_browser.contents))
-    Foo Bar
-    ...
+    Package bugs
     Foo Bar is subscribed to these packages.
     ...
     Totals 1 0 1 0
@@ -38,8 +37,7 @@
 
     >>> anon_browser.open("http://launchpad.dev/~name16/+packagebugs";)
     >>> print extract_text(find_main_content(anon_browser.contents))
-    Foo Bar
-    ...
+    Package bugs
     Foo Bar is subscribed to these packages.
     ...
     Totals 2 0 2 0

=== modified file 'lib/lp/bugs/stories/bugs/xx-bug-index.txt'
--- lib/lp/bugs/stories/bugs/xx-bug-index.txt	2014-11-25 07:56:07 +0000
+++ lib/lp/bugs/stories/bugs/xx-bug-index.txt	2014-11-27 07:55:25 +0000
@@ -14,7 +14,7 @@
 The breadcrumbs and other navigation include a link to the bug itself.
 
     >>> print_location(anon_browser.contents)
-    Hierarchy: Debian > ?mozilla-firefox? package > Bugs > Bug #2 (blackhole)
+    Hierarchy: Debian GNU/Linux > ?mozilla-firefox? package
     Tabs:
     * Overview - http://launchpad.dev/debian/+source/mozilla-firefox
     * Code - http://code.launchpad.dev/debian/+source/mozilla-firefox

=== modified file 'lib/lp/bugs/stories/patches-view/patches-view.txt'
--- lib/lp/bugs/stories/patches-view/patches-view.txt	2014-11-24 09:16:35 +0000
+++ lib/lp/bugs/stories/patches-view/patches-view.txt	2014-11-27 07:55:25 +0000
@@ -13,7 +13,7 @@
     ...     anybody = factory.makePerson()
     >>> with_anybody = with_person_logged_in(anybody)
     >>> patchy_product = with_anybody(factory.makeProduct)(
-    ...     name='patchy-product-1', displayname="Patchy 1")
+    ...     name='patchy-product-1', displayname="Patchy 1", title="Patchy 1")
     >>> transaction.commit()
 
 We don't see any patches when we open the patches view.
@@ -88,7 +88,7 @@
 The page title and other wording in the page reflects the contents.
 
     >>> print_location(anon_browser.contents)
-    Hierarchy: Patchy 1 > Bugs > Patch attachments in Patchy 1
+    Hierarchy: Patchy 1
     Tabs: ...
     Main heading: Patch attachments in Patchy 1
 
@@ -276,6 +276,6 @@
 The page title and other wording in the page reflects the contents.
 
     >>> print_location(anon_browser.contents)
-    Hierarchy: Patchy 1 > Bugs > Series trunk > Patch attachments in trunk
+    Hierarchy: Patchy 1 > Series trunk > Patch attachments in trunk
     Tabs: ...
     Main heading: Patch attachments in trunk

=== modified file 'lib/lp/code/browser/tests/test_sourcepackagerecipe.py'
--- lib/lp/code/browser/tests/test_sourcepackagerecipe.py	2014-11-24 05:59:01 +0000
+++ lib/lp/code/browser/tests/test_sourcepackagerecipe.py	2014-11-27 07:55:25 +0000
@@ -1084,7 +1084,7 @@
     def test_index(self):
         build = self.makeSuccessfulBuild()
         self.assertTextMatchesExpressionIgnoreWhitespace("""\
-            Master Chef Code Recipes cake_recipe
+            Recipes cake_recipe
             .*
             Description Edit
             This recipe .*changes.
@@ -1439,8 +1439,6 @@
         recipe = self.makeRecipe()
         pattern = dedent("""\
             Request builds for cake_recipe
-            Master Chef
-            Code
             Recipes
             cake_recipe
             Request builds for cake_recipe
@@ -1677,7 +1675,6 @@
         """Test the basic index page."""
         main_text = self.getMainText(self.makeBuild(), '+index')
         self.assertTextMatchesExpressionIgnoreWhitespace("""\
-            Owner Code PPA named build for Owner
             created .*
             Build status
             Needs building
@@ -1707,7 +1704,6 @@
         main_text = self.getMainText(
             release.source_package_recipe_build, '+index')
         self.assertTextMatchesExpressionIgnoreWhitespace("""\
-            Owner Code PPA named build for Owner
             created .*
             Build status
             Successfully built

=== modified file 'lib/lp/code/stories/branches/xx-branch-deletion.txt'
--- lib/lp/code/stories/branches/xx-branch-deletion.txt	2013-11-14 04:42:13 +0000
+++ lib/lp/code/stories/branches/xx-branch-deletion.txt	2014-11-27 07:55:25 +0000
@@ -38,7 +38,7 @@
     >>> delete_link.click()
     >>> print extract_text(find_main_content(browser.contents))
     Delete branch “lp://dev/~alice/earthlynx/to-delete”
-    Earth Lynx...
+    to-delete ...
     Branch deletion is permanent.
     or Cancel
 

=== modified file 'lib/lp/code/stories/branches/xx-branch-index.txt'
--- lib/lp/code/stories/branches/xx-branch-index.txt	2014-03-21 03:34:57 +0000
+++ lib/lp/code/stories/branches/xx-branch-index.txt	2014-11-27 07:55:25 +0000
@@ -426,7 +426,7 @@
     >>> browser.open(
     ...     'http://code.launchpad.dev/~name12/gnome-terminal/scanned')
     >>> print_location(browser.contents)
-    Hierarchy: GNOME Terminal > Code > scanned
+    Hierarchy: The GNOME Terminal Emulator
     Tabs:
     * Overview - http://launchpad.dev/gnome-terminal
     * Code (selected) - http://code.launchpad.dev/gnome-terminal
@@ -438,7 +438,7 @@
 
     >>> browser.open('http://code.launchpad.dev/~name12/+junk/junk.dev')
     >>> print_location(browser.contents)
-    Hierarchy: Sample Person > Code > junk.dev
+    Hierarchy: Sample Person
     Tabs:
     * Overview - http://launchpad.dev/~name12
     * Code (selected) - http://code.launchpad.dev/~name12

=== modified file 'lib/lp/registry/stories/gpg-coc/xx-gpg-coc.txt'
--- lib/lp/registry/stories/gpg-coc/xx-gpg-coc.txt	2014-09-01 12:57:09 +0000
+++ lib/lp/registry/stories/gpg-coc/xx-gpg-coc.txt	2014-11-27 07:55:25 +0000
@@ -352,7 +352,6 @@
     >>> browser.open('http://launchpad.dev/~name12/+codesofconduct')
     >>> print extract_text(find_main_content(browser.contents))
     Codes of Conduct for Sample Person
-    ...
     Launchpad records codes of conduct you sign as commitments to the
     principles of collaboration, tolerance and open communication that
     drive the open source community.
@@ -424,7 +423,6 @@
     >>> browser.open('http://launchpad.dev/~name12/+codesofconduct')
     >>> print extract_text(find_main_content(browser.contents))
     Codes of Conduct for Sample Person
-    ...
     Launchpad records codes of conduct you sign as commitments to the
     principles of collaboration, tolerance and open communication that
     drive the open source community.

=== modified file 'lib/lp/registry/stories/milestone/object-milestones.txt'
--- lib/lp/registry/stories/milestone/object-milestones.txt	2013-09-27 04:13:23 +0000
+++ lib/lp/registry/stories/milestone/object-milestones.txt	2014-11-27 07:55:25 +0000
@@ -162,7 +162,7 @@
     1.0 : Mozilla Firefox
 
     >>> print_location(anon_browser.contents)
-    Hierarchy: Mozilla Firefox > 1.0
+    Hierarchy: Mozilla Firefox
     Tabs:
     * Overview (selected) - http://launchpad.dev/firefox
     * Code - http://code.launchpad.dev/firefox
@@ -180,7 +180,7 @@
     3.1 : Debian
 
     >>> print_location(anon_browser.contents)
-    Hierarchy: Debian > 3.1
+    Hierarchy: Debian GNU/Linux
     Tabs:
     * Overview (selected) - http://launchpad.dev/debian
     * Code - http://code.launchpad.dev/debian

=== modified file 'lib/lp/registry/stories/person/xx-deactivate-account.txt'
--- lib/lp/registry/stories/person/xx-deactivate-account.txt	2014-02-19 02:11:16 +0000
+++ lib/lp/registry/stories/person/xx-deactivate-account.txt	2014-11-27 07:55:25 +0000
@@ -67,10 +67,6 @@
     ...     'mozilla-firefox/+bug/3')
     >>> print extract_text(find_main_content(browser.contents))
     Bug Title Test
-    Debian
-    “mozilla-firefox” package
-    Bugs
-    Bug #3
     ...
     Assigned to
     Milestone

=== modified file 'lib/lp/registry/stories/product/xx-product-files.txt'
--- lib/lp/registry/stories/product/xx-product-files.txt	2013-09-27 04:13:23 +0000
+++ lib/lp/registry/stories/product/xx-product-files.txt	2014-11-27 07:55:25 +0000
@@ -116,7 +116,6 @@
     >>> main_content = find_main_content(tbird_owner.contents)
     >>> print extract_text(main_content)
     Download project files
-    Mozilla Thunderbird...
     No download files exist for this project...
     Add download file to the trunk series for release: 0.8
 

=== modified file 'lib/lp/registry/stories/team-polls/create-polls.txt'
--- lib/lp/registry/stories/team-polls/create-polls.txt	2013-09-27 04:13:23 +0000
+++ lib/lp/registry/stories/team-polls/create-polls.txt	2014-11-27 07:55:25 +0000
@@ -112,7 +112,7 @@
     >>> team_admin_browser.title
     'Debian Project Leader Election 2080 : \xe2\x80\x9cUbuntu Team\xe2\x80\x9d team'
     >>> print_location(team_admin_browser.contents)
-    Hierarchy:  ?Ubuntu Team? team > Debian Project Leader Election 2080
+    Hierarchy:  ?Ubuntu Team? team
     Tabs:
     * Overview (selected) - http://launchpad.dev/~ubuntu-team
     * Code - http://code.launchpad.dev/~ubuntu-team

=== modified file 'lib/lp/registry/stories/teammembership/xx-member-renewed-membership.txt'
--- lib/lp/registry/stories/teammembership/xx-member-renewed-membership.txt	2014-11-14 12:43:34 +0000
+++ lib/lp/registry/stories/teammembership/xx-member-renewed-membership.txt	2014-11-27 07:55:25 +0000
@@ -43,7 +43,6 @@
     LookupError: label 'Renew'
     >>> print extract_text(find_tag_by_id(browser.contents, 'maincontent'))
     Renew membership of Karl Tilbury in Mirror Administrators
-    ...
     This membership cannot be renewed because Mirror Administrators
     (ubuntu-mirror-admins) is not a team that allows its members to renew
     their own memberships.
@@ -73,7 +72,6 @@
     LookupError: label 'Renew'
     >>> print extract_text(find_tag_by_id(browser.contents, 'maincontent'))
     Renew membership of Karl Tilbury in Mirror Administrators
-    ...
     This membership cannot be renewed because it is not set to expire in
     7 days or less. You or one of the team administrators has already
     renewed it.
@@ -106,7 +104,6 @@
     ...              'ubuntu-mirror-admins')
     >>> print extract_text(find_tag_by_id(browser.contents, 'maincontent'))
     Renew membership of Karl Tilbury in Mirror Administrators
-    ...
     This membership is going to expire ... from now. If you want to
     remain a member of Mirror Administrators, you must renew it.
     or Cancel
@@ -131,7 +128,6 @@
     LookupError: label 'Renew'
     >>> print extract_text(find_tag_by_id(browser.contents, 'maincontent'))
     Renew membership of Karl Tilbury in Mirror Administrators
-    ...
     This membership cannot be renewed because it is not set to expire in
     7 days or less. You or one of the team administrators has already
     renewed it.
@@ -161,7 +157,6 @@
     ...              '/+expiringmembership/ubuntu-mirror-admins')
     >>> print extract_text(find_tag_by_id(browser.contents, 'maincontent'))
     Renew membership of Landscape Developers in Mirror Administrators
-    ...
     This membership is going to expire ... from now. If you want this team
     to remain a member of Mirror Administrators, you must renew it.
     or Cancel
@@ -196,7 +191,6 @@
     ...              '/+expiringmembership/ubuntu-mirror-admins')
     >>> print extract_text(find_tag_by_id(browser.contents, 'maincontent'))
     Renew membership of Landscape Developers in Mirror Administrators
-    ...
     This membership cannot be renewed because it is not set to expire in
     7 days or less. Somebody else has already renewed it.
 

=== modified file 'lib/lp/soyuz/browser/tests/test_livefs.py'
--- lib/lp/soyuz/browser/tests/test_livefs.py	2014-06-20 12:11:13 +0000
+++ lib/lp/soyuz/browser/tests/test_livefs.py	2014-11-27 07:55:25 +0000
@@ -357,7 +357,7 @@
         build = self.makeBuild(
             status=BuildStatus.FULLYBUILT, duration=timedelta(minutes=30))
         self.assertTextMatchesExpressionIgnoreWhitespace("""\
-            Test Person Live filesystems livefs-name
+            Live filesystems livefs-name
             .*
             Live filesystem information
             Owner: Test Person

=== modified file 'lib/lp/soyuz/stories/distribution/xx-distribution-packages.txt'
--- lib/lp/soyuz/stories/distribution/xx-distribution-packages.txt	2014-11-25 07:56:07 +0000
+++ lib/lp/soyuz/stories/distribution/xx-distribution-packages.txt	2014-11-27 07:55:25 +0000
@@ -61,15 +61,6 @@
     The Mozilla Firefox web browser
     (Matching binaries: mozilla-firefox, mozilla-firefox-data.)
 
-The search page will also present commercial packages:
-
-    >>> browser.goBack()
-    >>> field = browser.getControl(name="text")
-    >>> field.value = 'commercialpackage'
-    >>> browser.getControl('Search', index=0).click()
-    >>> extract_text(find_main_content(browser.contents))
-    u"...commercialpackage... package..."
-
 Now try searching for text that we know to be in a change log entry, to
 prove that FTI works on change logs.  The text we're looking for is
 "placeholder" which is mentioned in the change log entry for pmount and
@@ -203,7 +194,7 @@
     \u201ciceweasel\u201d package : Ubuntu
 
     >>> print_location(user_browser.contents)
-    Hierarchy: Ubuntu > ?iceweasel? package
+    Hierarchy: Ubuntu Linux > ?iceweasel? package
     Tabs:
     * Overview (selected) - not linked
     * Code - http://code.launchpad.dev/ubuntu/+source/iceweasel
@@ -400,7 +391,7 @@
     Change log : \u201cfoobar\u201d package : Ubuntu
 
     >>> print_location(browser.contents)
-    Hierarchy: Ubuntu > ?foobar? package > Change log
+    Hierarchy: Ubuntu Linux > ?foobar? package
     Tabs:
     * Overview (selected) - http://launchpad.dev/ubuntu/+source/foobar
     * Code - http://code.launchpad.dev/ubuntu/+source/foobar
@@ -591,7 +582,7 @@
     Publishing history : \u201calsa-utils\u201d package : Ubuntu
 
     >>> print_location(anon_browser.contents)
-    Hierarchy: Ubuntu > ?alsa-utils? package > Publishing history
+    Hierarchy: Ubuntu Linux > ?alsa-utils? package
     Tabs:
     * Overview (selected) - http://launchpad.dev/ubuntu/+source/alsa-utils
     * Code - http://code.launchpad.dev/ubuntu/+source/alsa-utils

=== modified file 'lib/lp/soyuz/stories/packaging/package-pages-navigation.txt'
--- lib/lp/soyuz/stories/packaging/package-pages-navigation.txt	2014-11-26 23:50:26 +0000
+++ lib/lp/soyuz/stories/packaging/package-pages-navigation.txt	2014-11-27 07:55:25 +0000
@@ -16,7 +16,7 @@
 
     >>> anon_browser.open('http://launchpad.dev/ubuntu/+source/alsa-utils')
     >>> print_location(anon_browser.contents)
-    Hierarchy: Ubuntu > ?alsa-utils? package
+    Hierarchy: Ubuntu Linux > ?alsa-utils? package
     Tabs:
     * Overview (selected) - not linked
     * Code - http://code.launchpad.dev/ubuntu/+source/alsa-utils
@@ -28,7 +28,7 @@
 
     >>> anon_browser.open('http://bugs.launchpad.dev/ubuntu/+source/alsa-utils')
     >>> print_location(anon_browser.contents)
-    Hierarchy: Ubuntu > ?alsa-utils? package > Bugs
+    Hierarchy: Ubuntu Linux > ?alsa-utils? package
     Tabs:
     * Overview - http://launchpad.dev/ubuntu/+source/alsa-utils
     * Code - http://code.launchpad.dev/ubuntu/+source/alsa-utils
@@ -49,7 +49,7 @@
     >>> anon_browser.open(
     ...     'http://launchpad.dev/ubuntu/+source/alsa-utils/1.0.9a-4ubuntu1')
     >>> print_location(anon_browser.contents)
-    Hierarchy: Ubuntu > ?alsa-utils? package > 1.0.9a-4ubuntu1
+    Hierarchy: Ubuntu Linux > ?alsa-utils? package
     Tabs:
     * Overview (selected) - http://launchpad.dev/ubuntu/+source/alsa-utils
     * Code - http://code.launchpad.dev/ubuntu/+source/alsa-utils
@@ -68,7 +68,7 @@
     >>> anon_browser.open(
     ...     'http://launchpad.dev/ubuntu/+source/alsa-utils/1.0.9a-4ubuntu1/+build/11')
     >>> print_location(anon_browser.contents)
-    Hierarchy: Ubuntu > ?alsa-utils? package > 1.0.9a-4ubuntu1 > i386 build
+    Hierarchy: Ubuntu Linux > ?alsa-utils? package > 1.0.9a-4ubuntu1 > i386 build
     Tabs:
     * Overview (selected) - http://launchpad.dev/ubuntu/+source/alsa-utils
     * Code - http://code.launchpad.dev/ubuntu/+source/alsa-utils
@@ -87,7 +87,7 @@
     >>> anon_browser.open(
     ...     'http://launchpad.dev/ubuntu/hoary/+source/alsa-utils')
     >>> print_location(anon_browser.contents)
-    Hierarchy: Ubuntu > ?alsa-utils? package > Hoary (5.04)
+    Hierarchy: Ubuntu Linux > ?alsa-utils? package
     Tabs:
     * Overview (selected) - http://launchpad.dev/ubuntu/+source/alsa-utils
     * Code - http://code.launchpad.dev/ubuntu/+source/alsa-utils
@@ -105,7 +105,7 @@
 
     >>> anon_browser.open('http://launchpad.dev/ubuntu/hoary/i386')
     >>> print_location(anon_browser.contents)
-    Hierarchy: Ubuntu > Hoary (5.04) > i386
+    Hierarchy: Ubuntu Linux > Hoary (5.04) > i386
     Tabs:
     * Overview (selected) - http://launchpad.dev/ubuntu
     * Code - http://code.launchpad.dev/ubuntu
@@ -123,7 +123,7 @@
 
     >>> anon_browser.open('http://launchpad.dev/ubuntu/hoary/i386/pmount')
     >>> print_location(anon_browser.contents)
-    Hierarchy: Ubuntu > Hoary (5.04) > i386 > pmount
+    Hierarchy: Ubuntu Linux > Hoary (5.04) > i386 > pmount
     Tabs:
     * Overview (selected) - http://launchpad.dev/ubuntu
     * Code - http://code.launchpad.dev/ubuntu
@@ -142,7 +142,7 @@
     >>> anon_browser.open(
     ...     'http://launchpad.dev/ubuntu/hoary/i386/pmount/0.1-1')
     >>> print_location(anon_browser.contents)
-    Hierarchy: Ubuntu > Hoary (5.04) > i386 > pmount > 0.1-1
+    Hierarchy: Ubuntu Linux > Hoary (5.04) > i386 > pmount > 0.1-1
     Tabs:
     * Overview (selected) - http://launchpad.dev/ubuntu
     * Code - http://code.launchpad.dev/ubuntu

=== modified file 'lib/lp/soyuz/stories/ppa/xx-copy-packages.txt'
--- lib/lp/soyuz/stories/ppa/xx-copy-packages.txt	2014-09-01 10:52:54 +0000
+++ lib/lp/soyuz/stories/ppa/xx-copy-packages.txt	2014-11-27 07:55:25 +0000
@@ -318,10 +318,8 @@
 
     >>> print extract_text(find_main_content(jblack_browser.contents))
     i386 build of pmount 0.1-1 in ubuntu hoary RELEASE
-    James Blackwell
-    PPA for James Blackwell
-    i386 build of pmount 0.1-1
-    ...
+    PPA for James Blackwell i386 build of pmount 0.1-1
+    created ...
     Build status Needs building
     Cancel build
     Start

=== modified file 'lib/lp/soyuz/stories/ppa/xx-ppa-navigation.txt'
--- lib/lp/soyuz/stories/ppa/xx-ppa-navigation.txt	2014-07-24 09:37:03 +0000
+++ lib/lp/soyuz/stories/ppa/xx-ppa-navigation.txt	2014-11-27 07:55:25 +0000
@@ -48,7 +48,7 @@
 While navigating around the PPA the "structural location" includes a PPA:
 
     >>> print_location(anon_browser.contents)
-    Hierarchy: Celso Providelo > PPA for Celso Providelo
+    Hierarchy: Celso Providelo
     Tabs:
     * Overview (selected) - http://launchpad.dev/~cprov
     * Code - http://code.launchpad.dev/~cprov
@@ -69,7 +69,7 @@
     >>> cprov_browser.getControl("Save").click()
 
     >>> print_location(cprov_browser.contents)
-    Hierarchy: Celso Providelo > Default PPA
+    Hierarchy: Celso Providelo
     Tabs:
     * Overview (selected) - http://launchpad.dev/~cprov
     * Code - http://code.launchpad.dev/~cprov

=== modified file 'lib/lp/soyuz/stories/ppa/xx-ubuntu-ppas.txt'
--- lib/lp/soyuz/stories/ppa/xx-ubuntu-ppas.txt	2014-11-09 01:48:36 +0000
+++ lib/lp/soyuz/stories/ppa/xx-ubuntu-ppas.txt	2014-11-27 07:55:25 +0000
@@ -5,7 +5,7 @@
     >>> anon_browser.open("http://launchpad.dev/ubuntu";)
     >>> anon_browser.getLink("Personal Package Archives").click()
     >>> print_location(anon_browser.contents)
-    Hierarchy: Ubuntu > Personal Package Archives
+    Hierarchy: Ubuntu Linux
     Tabs:
     * Overview (selected) - http://launchpad.dev/ubuntu
     * Code - http://code.launchpad.dev/ubuntu
@@ -447,7 +447,6 @@
     >>> anon_browser.open("http://launchpad.dev/~no-priv/+archive/ubuntu/ppa";)
     >>> print extract_text(find_main_content(anon_browser.contents))
     PPA for No Privileges Person
-    ...
     PPA description
     I am not allowed to say, I have no privs.
     Adding this PPA to your system

=== modified file 'lib/lp/soyuz/stories/soyuz/xx-distribution-archives.txt'
--- lib/lp/soyuz/stories/soyuz/xx-distribution-archives.txt	2013-05-10 06:44:11 +0000
+++ lib/lp/soyuz/stories/soyuz/xx-distribution-archives.txt	2014-11-27 07:55:25 +0000
@@ -60,7 +60,6 @@
     >>> main_content = find_main_content(anon_browser.contents)
     >>> print extract_text(main_content)
     Copy Archives related to Ubuntu Linux
-    Ubuntu...
     'Copy' archives containing packages copied from other archives
     (the main archive or PPAs) for a distribution.
     ...

=== modified file 'lib/lp/soyuz/stories/soyuz/xx-distributionsourcepackagerelease-pages.txt'
--- lib/lp/soyuz/stories/soyuz/xx-distributionsourcepackagerelease-pages.txt	2014-11-25 06:06:45 +0000
+++ lib/lp/soyuz/stories/soyuz/xx-distributionsourcepackagerelease-pages.txt	2014-11-27 07:55:25 +0000
@@ -45,7 +45,7 @@
 they all point to the `DistributionSourcePackage` (parent) url.
 
     >>> print_location(anon_browser.contents)
-    Hierarchy: ubuntutest > ?testing-dspr? package > 1.0
+    Hierarchy: Ubuntu Test > ?testing-dspr? package
     Tabs:
     * Overview (selected) - http://launchpad.dev/ubuntutest/+source/testing-dspr
     * Code - http://code.launchpad.dev/ubuntutest/+source/testing-dspr
@@ -168,8 +168,6 @@
 
     >>> print extract_text(find_main_content(anon_browser.contents))
     Publishing history of ...testing-dspr... 1.0 source package in ubuntutest
-    ubuntutest
-    ...testing-dspr... package
     1.0
     Publishing history
     ...
@@ -290,9 +288,6 @@
 
     >>> print extract_text(find_main_content(user_browser.contents))
     Change log for ...testing-dspr... package in ubuntutest
-    ubuntutest
-    ...testing-dspr... package
-    Change log
     ...
     0.9
     Pending in breezy-autotest-release

=== modified file 'lib/lp/soyuz/stories/soyuz/xx-distroseries-binary-packages.txt'
--- lib/lp/soyuz/stories/soyuz/xx-distroseries-binary-packages.txt	2014-11-09 08:56:32 +0000
+++ lib/lp/soyuz/stories/soyuz/xx-distroseries-binary-packages.txt	2014-11-27 07:55:25 +0000
@@ -11,7 +11,7 @@
     >>> main_content = find_main_content(browser.contents)
     >>> print extract_text(main_content)
     Binary package “mozilla-firefox” in ubuntu warty
-    Ubuntu Warty (4.10) mozilla-firefox
+    Warty (4.10) mozilla-firefox
     Mozilla Firefox Web Browser
     Mozilla Firefox Web Browser is .....
     Source package
@@ -49,9 +49,8 @@
     >>> main_content = find_main_content(browser.contents)
     >>> print extract_text(main_content)
     Binary package “mozilla-firefox” in ubuntu hoary
-    Ubuntu Hoary (5.04) mozilla-firefox
+    Hoary (5.04) mozilla-firefox
     No summary available for mozilla-firefox in ubuntu hoary.
     No description available for mozilla-firefox in ubuntu hoary.
     Published versions
     Not published at present.
-

=== modified file 'lib/lp/soyuz/stories/soyuz/xx-sourcepackage-changelog.txt'
--- lib/lp/soyuz/stories/soyuz/xx-sourcepackage-changelog.txt	2014-11-26 23:50:26 +0000
+++ lib/lp/soyuz/stories/soyuz/xx-sourcepackage-changelog.txt	2014-11-27 07:55:25 +0000
@@ -6,7 +6,7 @@
     >>> user_browser.open(
     ...     "http://launchpad.dev/ubuntu/hoary/+source/pmount/+changelog";)
     >>> print_location(user_browser.contents)
-    Hierarchy: Ubuntu > ...pmount... package > Hoary (5.04) > Change log
+    Hierarchy: Ubuntu Linux > ...pmount... package > Hoary (5.04) > Change log
     Tabs:
     * Overview (selected) - http://launchpad.dev/ubuntu/+source/pmount
     * Code - http://code.launchpad.dev/ubuntu/+source/pmount

=== modified file 'lib/lp/testing/pages.py'
--- lib/lp/testing/pages.py	2014-06-27 08:27:31 +0000
+++ lib/lp/testing/pages.py	2014-11-27 07:55:25 +0000
@@ -7,6 +7,7 @@
 
 from datetime import datetime
 import doctest
+from itertools import chain
 import os
 import pdb
 import pprint
@@ -573,10 +574,11 @@
     The main heading is the first <h1> element in the page.
     """
     doc = find_tag_by_id(contents, 'document')
-    hierarchy = doc.find(attrs={'class': 'breadcrumbs'}).findAll(
-        recursive=False)
+    heading = doc.find(attrs={'id': 'watermark-heading'}).findAll('a')
+    container = doc.find(attrs={'class': 'breadcrumbs'})
+    hierarchy = container.findAll(recursive=False) if container else []
     segments = [extract_text(step).encode('us-ascii', 'replace')
-                for step in hierarchy]
+                for step in chain(heading, hierarchy)]
 
     if len(segments) == 0:
         breadcrumbs = 'None displayed'

=== modified file 'lib/lp/translations/stories/buildfarm/xx-build-summary.txt'
--- lib/lp/translations/stories/buildfarm/xx-build-summary.txt	2014-06-25 06:19:19 +0000
+++ lib/lp/translations/stories/buildfarm/xx-build-summary.txt	2014-11-27 07:55:25 +0000
@@ -94,7 +94,7 @@
 
     >>> user_browser.open(build_url)
     >>> print extract_text(find_main_content(user_browser.contents))
-    P...
+    created ...
     Build status
         Currently building
         Started ...
@@ -120,7 +120,7 @@
 
     >>> user_browser.open(build_url)
     >>> print extract_text(find_main_content(user_browser.contents))
-    P...
+    created ...
     Build status
         Currently building
         Started ...

=== modified file 'lib/lp/translations/stories/standalone/custom-language-codes.txt'
--- lib/lp/translations/stories/standalone/custom-language-codes.txt	2012-01-15 13:32:27 +0000
+++ lib/lp/translations/stories/standalone/custom-language-codes.txt	2014-11-27 07:55:25 +0000
@@ -100,7 +100,6 @@
     >>> main = find_main_content(owner_browser.contents)
     >>> print extract_text(main.renderContents())
     Custom language code  ...no... for Foo
-    Foo Translations Custom language code ...no...
     For Foo, uploads with the language code
     &ldquo;no&rdquo;
     are associated with the language

=== modified file 'lib/lp/translations/stories/standalone/xx-product-translations.txt'
--- lib/lp/translations/stories/standalone/xx-product-translations.txt	2010-12-02 12:08:05 +0000
+++ lib/lp/translations/stories/standalone/xx-product-translations.txt	2014-11-27 07:55:25 +0000
@@ -8,8 +8,6 @@
     Translations : Evolution
     >>> print extract_text(find_main_content(anon_browser.contents))
     Translation overview
-    Evolution
-    Translations
     ...
 
 A helper method to print out language chart.
@@ -80,8 +78,6 @@
     >>> unprivileged.open('http://translations.launchpad.dev/gnomebaker')
     >>> print extract_text(find_main_content(unprivileged.contents))
     Translation overview
-    gnomebaker
-    Translations
     Help for translations
     Launchpad does not know where
     gnomebaker translates its messages.
@@ -113,8 +109,6 @@
     >>> anon_browser.open('http://translations.launchpad.dev/gnomebaker')
     >>> print extract_text(find_main_content(anon_browser.contents))
     Translation overview
-    gnomebaker
-    Translations
     Help for translations
     Launchpad does not know where
     gnomebaker translates its messages.


Follow ups