Merge lp:~thumper/launchpad/code-import-machine-breadcrumb into lp:launchpad
- code-import-machine-breadcrumb
- Merge into devel
| Status: | Merged |
|---|---|
| Approved by: | Tim Penhey on 2010-04-28 |
| Approved revision: | no longer in the source branch. |
| Merged at revision: | not available |
| Proposed branch: | lp:~thumper/launchpad/code-import-machine-breadcrumb |
| Merge into: | lp:launchpad |
| Diff against target: |
1158 lines (+337/-369) 15 files modified
lib/canonical/launchpad/doc/canonical_url_examples.txt (+1/-1) lib/canonical/launchpad/webapp/tests/test_breadcrumbs.py (+24/-36) lib/lp/answers/browser/tests/test_breadcrumbs.py (+6/-12) lib/lp/blueprints/browser/tests/test_breadcrumbs.py (+5/-9) lib/lp/bugs/browser/configure.zcml (+2/-1) lib/lp/bugs/browser/tests/test_breadcrumbs.py (+32/-60) lib/lp/code/browser/codeimportmachine.py (+9/-0) lib/lp/code/browser/configure.zcml (+13/-0) lib/lp/code/browser/tests/test_breadcrumbs.py (+25/-0) lib/lp/code/configure.zcml (+0/-6) lib/lp/registry/browser/tests/test_breadcrumbs.py (+10/-26) lib/lp/soyuz/browser/tests/test_breadcrumbs.py (+14/-34) lib/lp/testing/breadcrumbs.py (+40/-56) lib/lp/testing/publication.py (+57/-0) lib/lp/translations/browser/tests/test_breadcrumbs.py (+99/-128) |
| To merge this branch: | bzr merge lp:~thumper/launchpad/code-import-machine-breadcrumb |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Michael Hudson-Doyle | 2010-04-28 | Approve on 2010-04-28 | |
|
Review via email:
|
|||
Commit Message
Add breadcrumbs for code import machines, and refactor (almost completely) the base breadcrumb test case.
Description of the Change
Add breadcrumbs for code import machines.
Also as part of this I wanted to "fix" the BaseBreadcrumbT
The CustomMachine part of the diff may appear, but that has been landed rs=flacoste into devel.
I moved the BaseBreadcrumbT
BugComments were missing the rootsite for their browser:url, causing a breadcrumb failure. The test for this breadcrumb was completely wrong and wasn't testing the comment breadcrumb at all.
The test for the breadcrumbs for a private bug is completely whack as the bug would never be traversed to in order to generate the breadcrumbs, so I deleted it.
Minor tweaks to the translation breadcrumb tests to make them pass.
| Tim Penhey (thumper) wrote : | # |
I've removed or renamed the _getBreadcrumb methods and dealt with the extensive test breakages.
Preview Diff
| 1 | === modified file 'lib/canonical/launchpad/doc/canonical_url_examples.txt' |
| 2 | --- lib/canonical/launchpad/doc/canonical_url_examples.txt 2010-04-16 15:06:55 +0000 |
| 3 | +++ lib/canonical/launchpad/doc/canonical_url_examples.txt 2010-04-28 21:41:35 +0000 |
| 4 | @@ -275,7 +275,7 @@ |
| 5 | >>> bug_comment = BugComment( |
| 6 | ... 1, bug_one.initial_message, bugtask_one, True) |
| 7 | >>> canonical_url(bug_comment) |
| 8 | - u'http://launchpad.dev/firefox/+bug/1/comments/1' |
| 9 | + u'http://bugs.launchpad.dev/firefox/+bug/1/comments/1' |
| 10 | |
| 11 | An IBugNomination. |
| 12 | |
| 13 | |
| 14 | === modified file 'lib/canonical/launchpad/webapp/tests/test_breadcrumbs.py' |
| 15 | --- lib/canonical/launchpad/webapp/tests/test_breadcrumbs.py 2009-09-21 16:21:50 +0000 |
| 16 | +++ lib/canonical/launchpad/webapp/tests/test_breadcrumbs.py 2010-04-28 21:41:35 +0000 |
| 17 | @@ -13,9 +13,8 @@ |
| 18 | from canonical.launchpad.webapp.interfaces import ICanonicalUrlData |
| 19 | from canonical.launchpad.webapp.publisher import canonical_url |
| 20 | from canonical.launchpad.webapp.servers import LaunchpadTestRequest |
| 21 | -from canonical.launchpad.webapp.tests.breadcrumbs import ( |
| 22 | - BaseBreadcrumbTestCase) |
| 23 | from lp.testing import login, TestCase |
| 24 | +from lp.testing.breadcrumbs import BaseBreadcrumbTestCase |
| 25 | |
| 26 | |
| 27 | class Cookbook: |
| 28 | @@ -52,19 +51,17 @@ |
| 29 | self.product_url = canonical_url(self.product) |
| 30 | |
| 31 | def test_default_page(self): |
| 32 | - urls = self._getBreadcrumbsURLs( |
| 33 | - self.product_url, [self.root, self.product]) |
| 34 | - self.assertEquals(urls, [self.product_url]) |
| 35 | + self.assertBreadcrumbUrls([self.product_url], self.product) |
| 36 | |
| 37 | def test_non_default_page(self): |
| 38 | + crumbs = self.getBreadcrumbsForObject(self.product, '+download') |
| 39 | downloads_url = "%s/+download" % self.product_url |
| 40 | - urls = self._getBreadcrumbsURLs( |
| 41 | - downloads_url, [self.root, self.product]) |
| 42 | - self.assertEquals(urls, [self.product_url, downloads_url]) |
| 43 | - texts = self._getBreadcrumbsTexts( |
| 44 | - downloads_url, [self.root, self.product]) |
| 45 | - self.assertEquals(texts[-1], |
| 46 | - '%s project files' % self.product.displayname) |
| 47 | + self.assertEquals( |
| 48 | + [self.product_url, downloads_url], |
| 49 | + [crumb.url for crumb in crumbs]) |
| 50 | + self.assertEquals( |
| 51 | + '%s project files' % self.product.displayname, |
| 52 | + crumbs[-1].text) |
| 53 | |
| 54 | def test_zope_i18n_Messages_are_interpolated(self): |
| 55 | # Views can use zope.i18nmessageid.Message as their title when they |
| 56 | @@ -108,31 +105,25 @@ |
| 57 | self.package_bugtask_url = canonical_url(self.package_bugtask) |
| 58 | |
| 59 | def test_root_on_mainsite(self): |
| 60 | - urls = self._getBreadcrumbsURLs('http://launchpad.dev/', [self.root]) |
| 61 | - self.assertEquals(urls, []) |
| 62 | + crumbs = self.getBreadcrumbsForUrl('http://launchpad.dev/') |
| 63 | + self.assertEquals(crumbs, []) |
| 64 | |
| 65 | def test_product_on_mainsite(self): |
| 66 | - urls = self._getBreadcrumbsURLs( |
| 67 | - self.product_url, [self.root, self.product]) |
| 68 | - self.assertEquals(urls, [self.product_url]) |
| 69 | + self.assertBreadcrumbUrls([self.product_url], self.product) |
| 70 | |
| 71 | def test_root_on_vhost(self): |
| 72 | - urls = self._getBreadcrumbsURLs( |
| 73 | - 'http://bugs.launchpad.dev/', [self.root]) |
| 74 | - self.assertEquals(urls, []) |
| 75 | + crumbs = self.getBreadcrumbsForUrl('http://bugs.launchpad.dev/') |
| 76 | + self.assertEquals(crumbs, []) |
| 77 | |
| 78 | def test_product_on_vhost(self): |
| 79 | - urls = self._getBreadcrumbsURLs( |
| 80 | - self.product_bugs_url, [self.root, self.product]) |
| 81 | - self.assertEquals(urls, [self.product_url, self.product_bugs_url]) |
| 82 | + self.assertBreadcrumbUrls( |
| 83 | + [self.product_url, self.product_bugs_url], |
| 84 | + self.product, rootsite='bugs') |
| 85 | |
| 86 | def test_product_bugtask(self): |
| 87 | - urls = self._getBreadcrumbsURLs( |
| 88 | - self.product_bugtask_url, |
| 89 | - [self.root, self.product, self.product_bugtask]) |
| 90 | - self.assertEquals( |
| 91 | - urls, [self.product_url, self.product_bugs_url, |
| 92 | - self.product_bugtask_url]) |
| 93 | + self.assertBreadcrumbUrls( |
| 94 | + [self.product_url, self.product_bugs_url, self.product_bugtask_url], |
| 95 | + self.product_bugtask) |
| 96 | |
| 97 | def test_package_bugtask(self): |
| 98 | target = self.package_bugtask.target |
| 99 | @@ -140,14 +131,11 @@ |
| 100 | distroseries_url = canonical_url(target.distroseries) |
| 101 | package_url = canonical_url(target) |
| 102 | package_bugs_url = canonical_url(target, rootsite='bugs') |
| 103 | - urls = self._getBreadcrumbsURLs( |
| 104 | - self.package_bugtask_url, |
| 105 | - [self.root, target.distribution, target.distroseries, target, |
| 106 | - self.package_bugtask]) |
| 107 | - self.assertEquals( |
| 108 | - urls, |
| 109 | + |
| 110 | + self.assertBreadcrumbUrls( |
| 111 | [distro_url, distroseries_url, package_url, package_bugs_url, |
| 112 | - self.package_bugtask_url]) |
| 113 | + self.package_bugtask_url], |
| 114 | + self.package_bugtask) |
| 115 | |
| 116 | |
| 117 | def test_suite(): |
| 118 | |
| 119 | === modified file 'lib/lp/answers/browser/tests/test_breadcrumbs.py' |
| 120 | --- lib/lp/answers/browser/tests/test_breadcrumbs.py 2010-02-17 11:13:06 +0000 |
| 121 | +++ lib/lp/answers/browser/tests/test_breadcrumbs.py 2010-04-28 21:41:35 +0000 |
| 122 | @@ -6,10 +6,9 @@ |
| 123 | import unittest |
| 124 | |
| 125 | from canonical.launchpad.webapp.publisher import canonical_url |
| 126 | -from canonical.launchpad.webapp.tests.breadcrumbs import ( |
| 127 | - BaseBreadcrumbTestCase) |
| 128 | |
| 129 | from lp.testing import login_person |
| 130 | +from lp.testing.breadcrumbs import BaseBreadcrumbTestCase |
| 131 | |
| 132 | |
| 133 | class TestQuestionTargetProjectAndPersonBreadcrumbOnAnswersVHost( |
| 134 | @@ -36,22 +35,19 @@ |
| 135 | self.project, rootsite='answers') |
| 136 | |
| 137 | def test_product(self): |
| 138 | - crumbs = self._getBreadcrumbs( |
| 139 | - self.product_questions_url, [self.root, self.product]) |
| 140 | + crumbs = self.getBreadcrumbsForObject(self.product, rootsite='answers') |
| 141 | last_crumb = crumbs[-1] |
| 142 | self.assertEquals(last_crumb.url, self.product_questions_url) |
| 143 | self.assertEquals(last_crumb.text, 'Questions') |
| 144 | |
| 145 | def test_project(self): |
| 146 | - crumbs = self._getBreadcrumbs( |
| 147 | - self.project_questions_url, [self.root, self.project]) |
| 148 | + crumbs = self.getBreadcrumbsForObject(self.project, rootsite='answers') |
| 149 | last_crumb = crumbs[-1] |
| 150 | self.assertEquals(last_crumb.url, self.project_questions_url) |
| 151 | self.assertEquals(last_crumb.text, 'Questions') |
| 152 | |
| 153 | def test_person(self): |
| 154 | - crumbs = self._getBreadcrumbs( |
| 155 | - self.person_questions_url, [self.root, self.person]) |
| 156 | + crumbs = self.getBreadcrumbsForObject(self.person, rootsite='answers') |
| 157 | last_crumb = crumbs[-1] |
| 158 | self.assertEquals(last_crumb.url, self.person_questions_url) |
| 159 | self.assertEquals(last_crumb.text, 'Questions') |
| 160 | @@ -69,16 +65,14 @@ |
| 161 | self.question = self.factory.makeQuestion( |
| 162 | target=self.product, title='Seeds are hard to chew') |
| 163 | self.question_url = canonical_url(self.question, rootsite='answers') |
| 164 | - crumbs = self._getBreadcrumbs( |
| 165 | - self.question_url, [self.root, self.product, self.question]) |
| 166 | + crumbs = self.getBreadcrumbsForObject(self.question) |
| 167 | last_crumb = crumbs[-1] |
| 168 | self.assertEquals(last_crumb.text, 'Question #%d' % self.question.id) |
| 169 | |
| 170 | def test_faq(self): |
| 171 | self.faq = self.factory.makeFAQ(target=self.product, title='Seedless') |
| 172 | self.faq_url = canonical_url(self.faq, rootsite='answers') |
| 173 | - crumbs = self._getBreadcrumbs( |
| 174 | - self.faq_url, [self.root, self.product, self.faq]) |
| 175 | + crumbs = self.getBreadcrumbsForObject(self.faq) |
| 176 | last_crumb = crumbs[-1] |
| 177 | self.assertEquals(last_crumb.text, 'FAQ #%d' % self.faq.id) |
| 178 | |
| 179 | |
| 180 | === modified file 'lib/lp/blueprints/browser/tests/test_breadcrumbs.py' |
| 181 | --- lib/lp/blueprints/browser/tests/test_breadcrumbs.py 2009-09-22 15:02:41 +0000 |
| 182 | +++ lib/lp/blueprints/browser/tests/test_breadcrumbs.py 2010-04-28 21:41:35 +0000 |
| 183 | @@ -6,8 +6,8 @@ |
| 184 | import unittest |
| 185 | |
| 186 | from canonical.launchpad.webapp.publisher import canonical_url |
| 187 | -from canonical.launchpad.webapp.tests.breadcrumbs import ( |
| 188 | - BaseBreadcrumbTestCase) |
| 189 | + |
| 190 | +from lp.testing.breadcrumbs import BaseBreadcrumbTestCase |
| 191 | |
| 192 | |
| 193 | class TestHasSpecificationsBreadcrumbOnBlueprintsVHost( |
| 194 | @@ -25,15 +25,13 @@ |
| 195 | self.product, rootsite='blueprints') |
| 196 | |
| 197 | def test_product(self): |
| 198 | - crumbs = self._getBreadcrumbs( |
| 199 | - self.product_specs_url, [self.root, self.product]) |
| 200 | + crumbs = self.getBreadcrumbsForObject(self.product, rootsite='blueprints') |
| 201 | last_crumb = crumbs[-1] |
| 202 | self.assertEquals(last_crumb.url, self.product_specs_url) |
| 203 | self.assertEquals(last_crumb.text, 'Blueprints') |
| 204 | |
| 205 | def test_person(self): |
| 206 | - crumbs = self._getBreadcrumbs( |
| 207 | - self.person_specs_url, [self.root, self.person]) |
| 208 | + crumbs = self.getBreadcrumbsForObject(self.person, rootsite='blueprints') |
| 209 | last_crumb = crumbs[-1] |
| 210 | self.assertEquals(last_crumb.url, self.person_specs_url) |
| 211 | self.assertEquals(last_crumb.text, 'Blueprints') |
| 212 | @@ -52,9 +50,7 @@ |
| 213 | self.specification, rootsite='blueprints') |
| 214 | |
| 215 | def test_specification(self): |
| 216 | - crumbs = self._getBreadcrumbs( |
| 217 | - self.specification_url, |
| 218 | - [self.root, self.product, self.specification]) |
| 219 | + crumbs = self.getBreadcrumbsForObject(self.specification) |
| 220 | last_crumb = crumbs[-1] |
| 221 | self.assertEquals(last_crumb.url, self.specification_url) |
| 222 | self.assertEquals( |
| 223 | |
| 224 | === modified file 'lib/lp/bugs/browser/configure.zcml' |
| 225 | --- lib/lp/bugs/browser/configure.zcml 2010-03-11 01:39:25 +0000 |
| 226 | +++ lib/lp/bugs/browser/configure.zcml 2010-04-28 21:41:35 +0000 |
| 227 | @@ -163,7 +163,8 @@ |
| 228 | <browser:url |
| 229 | for="canonical.launchpad.interfaces.IBugComment" |
| 230 | path_expression="string:comments/${index}" |
| 231 | - attribute_to_parent="bugtask"/> |
| 232 | + attribute_to_parent="bugtask" |
| 233 | + rootsite="bugs"/> |
| 234 | <browser:page |
| 235 | for="canonical.launchpad.interfaces.IBugComment" |
| 236 | name="+index" |
| 237 | |
| 238 | === modified file 'lib/lp/bugs/browser/tests/test_breadcrumbs.py' |
| 239 | --- lib/lp/bugs/browser/tests/test_breadcrumbs.py 2010-03-22 18:39:24 +0000 |
| 240 | +++ lib/lp/bugs/browser/tests/test_breadcrumbs.py 2010-04-28 21:41:35 +0000 |
| 241 | @@ -8,10 +8,10 @@ |
| 242 | from zope.component import getUtility |
| 243 | |
| 244 | from canonical.launchpad.webapp.publisher import canonical_url |
| 245 | -from canonical.launchpad.webapp.tests.breadcrumbs import ( |
| 246 | - BaseBreadcrumbTestCase) |
| 247 | + |
| 248 | from lp.bugs.interfaces.bugtracker import IBugTrackerSet |
| 249 | -from lp.testing import ANONYMOUS, login |
| 250 | +from lp.testing import login_person |
| 251 | +from lp.testing.breadcrumbs import BaseBreadcrumbTestCase |
| 252 | |
| 253 | |
| 254 | class TestBugTaskBreadcrumb(BaseBreadcrumbTestCase): |
| 255 | @@ -21,54 +21,35 @@ |
| 256 | product = self.factory.makeProduct( |
| 257 | name='crumb-tester', displayname="Crumb Tester") |
| 258 | self.bug = self.factory.makeBug(product=product) |
| 259 | - self.bugtask_url = canonical_url( |
| 260 | - self.bug.default_bugtask, rootsite='bugs') |
| 261 | - self.traversed_objects = [ |
| 262 | - self.root, product, self.bug.default_bugtask] |
| 263 | + self.bugtask = self.bug.default_bugtask |
| 264 | + self.bugtask_url = canonical_url(self.bugtask, rootsite='bugs') |
| 265 | |
| 266 | def test_bugtask(self): |
| 267 | - urls = self._getBreadcrumbsURLs( |
| 268 | - self.bugtask_url, self.traversed_objects) |
| 269 | - self.assertEquals(urls[-1], self.bugtask_url) |
| 270 | - texts = self._getBreadcrumbsTexts( |
| 271 | - self.bugtask_url, self.traversed_objects) |
| 272 | - self.assertEquals(texts[-1], "Bug #%d" % self.bug.id) |
| 273 | + crumbs = self.getBreadcrumbsForObject(self.bugtask) |
| 274 | + last_crumb = crumbs[-1] |
| 275 | + self.assertEquals(self.bugtask_url, last_crumb.url) |
| 276 | + self.assertEquals("Bug #%d" % self.bug.id, last_crumb.text) |
| 277 | |
| 278 | def test_bugtask_child(self): |
| 279 | - url = canonical_url( |
| 280 | - self.bug.default_bugtask, rootsite='bugs', view_name='+activity') |
| 281 | - urls = self._getBreadcrumbsURLs(url, self.traversed_objects) |
| 282 | - self.assertEquals(urls[-1], "%s/+activity" % self.bugtask_url) |
| 283 | - self.assertEquals(urls[-2], self.bugtask_url) |
| 284 | - texts = self._getBreadcrumbsTexts(url, self.traversed_objects) |
| 285 | - self.assertEquals(texts[-2], "Bug #%d" % self.bug.id) |
| 286 | + crumbs = self.getBreadcrumbsForObject(self.bugtask, view_name='+activity') |
| 287 | + self.assertEquals(crumbs[-1].url, "%s/+activity" % self.bugtask_url) |
| 288 | + self.assertEquals(crumbs[-2].url, self.bugtask_url) |
| 289 | + self.assertEquals(crumbs[-2].text, "Bug #%d" % self.bug.id) |
| 290 | |
| 291 | def test_bugtask_comment(self): |
| 292 | - login('foo.bar@canonical.com') |
| 293 | + login_person(self.bug.owner) |
| 294 | comment = self.factory.makeBugComment( |
| 295 | bug=self.bug, owner=self.bug.owner, |
| 296 | subject="test comment subject", body="test comment body") |
| 297 | - url = canonical_url(comment, rootsite='bugs') |
| 298 | - urls = self._getBreadcrumbsURLs(url, self.traversed_objects) |
| 299 | - texts = self._getBreadcrumbsTexts(url, self.traversed_objects) |
| 300 | - self.assertEquals(url, "%s/comments/1" % self.bugtask_url) |
| 301 | - self.assertEquals(urls[-1], "%s" % self.bugtask_url) |
| 302 | - self.assertEquals(texts[-1], "Bug #%d" % self.bug.id) |
| 303 | - |
| 304 | - def test_bugtask_private_bug(self): |
| 305 | - # A breadcrumb is not generated for a bug that the user does |
| 306 | - # not have permission to view. |
| 307 | - login('foo.bar@canonical.com') |
| 308 | - self.bug.setPrivate(True, self.bug.owner) |
| 309 | - login(ANONYMOUS) |
| 310 | - url = canonical_url(self.bug.default_bugtask, rootsite='bugs') |
| 311 | - self.assertEquals( |
| 312 | - ['http://launchpad.dev/crumb-tester', |
| 313 | - 'http://bugs.launchpad.dev/crumb-tester'], |
| 314 | - self._getBreadcrumbsURLs(url, self.traversed_objects)) |
| 315 | - self.assertEquals( |
| 316 | - ["Crumb Tester", "Bugs"], |
| 317 | - self._getBreadcrumbsTexts(url, self.traversed_objects)) |
| 318 | + expected_breadcrumbs = [ |
| 319 | + ('Crumb Tester', 'http://launchpad.dev/crumb-tester'), |
| 320 | + ('Bugs', 'http://bugs.launchpad.dev/crumb-tester'), |
| 321 | + ('Bug #%s' % self.bug.id, |
| 322 | + 'http://bugs.launchpad.dev/crumb-tester/+bug/%s' % self.bug.id), |
| 323 | + ('Comment #1', |
| 324 | + 'http://bugs.launchpad.dev/crumb-tester/+bug/%s/comments/1' % self.bug.id), |
| 325 | + ] |
| 326 | + self.assertBreadcrumbs(expected_breadcrumbs, comment) |
| 327 | |
| 328 | |
| 329 | class TestBugTrackerBreadcrumbs(BaseBreadcrumbTestCase): |
| 330 | @@ -84,28 +65,19 @@ |
| 331 | |
| 332 | def test_bug_tracker_set(self): |
| 333 | # Check TestBugTrackerSetBreadcrumb. |
| 334 | - traversed_objects = [ |
| 335 | - self.root, self.bug_tracker_set] |
| 336 | - urls = self._getBreadcrumbsURLs( |
| 337 | - self.bug_tracker_set_url, traversed_objects) |
| 338 | - self.assertEquals(self.bug_tracker_set_url, urls[-1]) |
| 339 | - texts = self._getBreadcrumbsTexts( |
| 340 | - self.bug_tracker_set_url, traversed_objects) |
| 341 | - self.assertEquals("Bug trackers", texts[-1]) |
| 342 | + expected_breadcrumbs = [ |
| 343 | + ('Bug trackers', self.bug_tracker_set_url), |
| 344 | + ] |
| 345 | + self.assertBreadcrumbs(expected_breadcrumbs, self.bug_tracker_set) |
| 346 | |
| 347 | def test_bug_tracker(self): |
| 348 | # Check TestBugTrackerBreadcrumb (and |
| 349 | # TestBugTrackerSetBreadcrumb). |
| 350 | - traversed_objects = [ |
| 351 | - self.root, self.bug_tracker_set, self.bug_tracker] |
| 352 | - urls = self._getBreadcrumbsURLs( |
| 353 | - self.bug_tracker_url, traversed_objects) |
| 354 | - self.assertEquals(self.bug_tracker_url, urls[-1]) |
| 355 | - self.assertEquals(self.bug_tracker_set_url, urls[-2]) |
| 356 | - texts = self._getBreadcrumbsTexts( |
| 357 | - self.bug_tracker_url, traversed_objects) |
| 358 | - self.assertEquals(self.bug_tracker.title, texts[-1]) |
| 359 | - self.assertEquals("Bug trackers", texts[-2]) |
| 360 | + expected_breadcrumbs = [ |
| 361 | + ('Bug trackers', self.bug_tracker_set_url), |
| 362 | + (self.bug_tracker.title, self.bug_tracker_url), |
| 363 | + ] |
| 364 | + self.assertBreadcrumbs(expected_breadcrumbs, self.bug_tracker) |
| 365 | |
| 366 | |
| 367 | def test_suite(): |
| 368 | |
| 369 | === modified file 'lib/lp/code/browser/codeimportmachine.py' |
| 370 | --- lib/lp/code/browser/codeimportmachine.py 2009-08-24 20:28:33 +0000 |
| 371 | +++ lib/lp/code/browser/codeimportmachine.py 2010-04-28 21:41:35 +0000 |
| 372 | @@ -6,6 +6,7 @@ |
| 373 | __metaclass__ = type |
| 374 | |
| 375 | __all__ = [ |
| 376 | + 'CodeImportMachineBreadcrumb', |
| 377 | 'CodeImportMachineSetBreadcrumb', |
| 378 | 'CodeImportMachineSetNavigation', |
| 379 | 'CodeImportMachineSetView', |
| 380 | @@ -30,6 +31,14 @@ |
| 381 | from lazr.delegates import delegates |
| 382 | |
| 383 | |
| 384 | +class CodeImportMachineBreadcrumb(Breadcrumb): |
| 385 | + """An `IBreadcrumb` that uses the machines hostname.""" |
| 386 | + |
| 387 | + @property |
| 388 | + def text(self): |
| 389 | + return self.context.hostname |
| 390 | + |
| 391 | + |
| 392 | class CodeImportMachineSetNavigation(Navigation): |
| 393 | """Navigation methods for ICodeImportMachineSet.""" |
| 394 | usedfor = ICodeImportMachineSet |
| 395 | |
| 396 | === modified file 'lib/lp/code/browser/configure.zcml' |
| 397 | --- lib/lp/code/browser/configure.zcml 2010-04-19 03:44:27 +0000 |
| 398 | +++ lib/lp/code/browser/configure.zcml 2010-04-28 21:41:35 +0000 |
| 399 | @@ -1055,6 +1055,19 @@ |
| 400 | for="lp.code.interfaces.branchmergeproposal.IBranchMergeProposal" |
| 401 | factory="lp.code.browser.branchmergeproposal.BranchMergeProposalBreadcrumb" |
| 402 | permission="zope.Public"/> |
| 403 | + |
| 404 | + <adapter |
| 405 | + provides="canonical.launchpad.webapp.interfaces.IBreadcrumb" |
| 406 | + for="lp.code.interfaces.codeimportmachine.ICodeImportMachine" |
| 407 | + factory="lp.code.browser.codeimportmachine.CodeImportMachineBreadcrumb" |
| 408 | + permission="zope.Public"/> |
| 409 | + |
| 410 | + <adapter |
| 411 | + provides="canonical.launchpad.webapp.interfaces.IBreadcrumb" |
| 412 | + for="lp.code.interfaces.codeimportmachine.ICodeImportMachineSet" |
| 413 | + factory="lp.code.browser.codeimportmachine.CodeImportMachineSetBreadcrumb" |
| 414 | + permission="zope.Public"/> |
| 415 | + |
| 416 | <adapter |
| 417 | factory="lp.code.browser.branchmergeproposal.PreviewDiffHTMLRepresentation" |
| 418 | name="lazr.restful.EntryResource"/> |
| 419 | |
| 420 | === added file 'lib/lp/code/browser/tests/test_breadcrumbs.py' |
| 421 | --- lib/lp/code/browser/tests/test_breadcrumbs.py 1970-01-01 00:00:00 +0000 |
| 422 | +++ lib/lp/code/browser/tests/test_breadcrumbs.py 2010-04-28 21:41:35 +0000 |
| 423 | @@ -0,0 +1,25 @@ |
| 424 | +# Copyright 2010 Canonical Ltd. This software is licensed under the |
| 425 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
| 426 | + |
| 427 | +__metaclass__ = type |
| 428 | + |
| 429 | +import unittest |
| 430 | + |
| 431 | +from lp.testing.breadcrumbs import BaseBreadcrumbTestCase |
| 432 | + |
| 433 | + |
| 434 | +class TestCodeImportMachineBreadcrumb(BaseBreadcrumbTestCase): |
| 435 | + """Test breadcrumbs for an `ICodeImportMachine`.""" |
| 436 | + |
| 437 | + def test_machine(self): |
| 438 | + machine = self.factory.makeCodeImportMachine(hostname='apollo') |
| 439 | + expected = [ |
| 440 | + ('Code Import System', 'http://code.launchpad.dev/+code-imports'), |
| 441 | + ('Machines', 'http://code.launchpad.dev/+code-imports/+machines'), |
| 442 | + ('apollo', |
| 443 | + 'http://code.launchpad.dev/+code-imports/+machines/apollo')] |
| 444 | + self.assertBreadcrumbs(expected, machine) |
| 445 | + |
| 446 | + |
| 447 | +def test_suite(): |
| 448 | + return unittest.TestLoader().loadTestsFromName(__name__) |
| 449 | |
| 450 | === modified file 'lib/lp/code/configure.zcml' |
| 451 | --- lib/lp/code/configure.zcml 2010-04-23 02:35:47 +0000 |
| 452 | +++ lib/lp/code/configure.zcml 2010-04-28 21:41:35 +0000 |
| 453 | @@ -64,12 +64,6 @@ |
| 454 | appropriate. --> |
| 455 | </class> |
| 456 | |
| 457 | - <adapter |
| 458 | - provides="canonical.launchpad.webapp.interfaces.IBreadcrumb" |
| 459 | - for="lp.code.interfaces.codeimportmachine.ICodeImportMachineSet" |
| 460 | - factory="lp.code.browser.codeimportmachine.CodeImportMachineSetBreadcrumb" |
| 461 | - permission="zope.Public"/> |
| 462 | - |
| 463 | <!-- CodeImportMachineSet --> |
| 464 | |
| 465 | <securedutility |
| 466 | |
| 467 | === modified file 'lib/lp/registry/browser/tests/test_breadcrumbs.py' |
| 468 | --- lib/lp/registry/browser/tests/test_breadcrumbs.py 2009-11-25 15:08:30 +0000 |
| 469 | +++ lib/lp/registry/browser/tests/test_breadcrumbs.py 2010-04-28 21:41:35 +0000 |
| 470 | @@ -9,8 +9,8 @@ |
| 471 | |
| 472 | from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities |
| 473 | from canonical.launchpad.webapp.publisher import canonical_url |
| 474 | -from canonical.launchpad.webapp.tests.breadcrumbs import ( |
| 475 | - BaseBreadcrumbTestCase) |
| 476 | + |
| 477 | +from lp.testing.breadcrumbs import BaseBreadcrumbTestCase |
| 478 | |
| 479 | |
| 480 | class TestDistroseriesBreadcrumb(BaseBreadcrumbTestCase): |
| 481 | @@ -25,9 +25,7 @@ |
| 482 | self.distroseries_url = canonical_url(self.distroseries) |
| 483 | |
| 484 | def test_distroseries(self): |
| 485 | - crumbs = self._getBreadcrumbs( |
| 486 | - self.distroseries_url, |
| 487 | - [self.root, self.distribution, self.distroseries]) |
| 488 | + crumbs = self.getBreadcrumbsForObject(self.distroseries) |
| 489 | last_crumb = crumbs[-1] |
| 490 | self.assertEqual(self.distroseries.named_version, last_crumb.text) |
| 491 | |
| 492 | @@ -46,9 +44,7 @@ |
| 493 | mirror = self.factory.makeMirror( |
| 494 | distribution=self.distribution, |
| 495 | displayname=displayname) |
| 496 | - crumbs = self._getBreadcrumbs( |
| 497 | - canonical_url(mirror), |
| 498 | - [self.root, self.distribution, mirror]) |
| 499 | + crumbs = self.getBreadcrumbsForObject(mirror) |
| 500 | last_crumb = crumbs[-1] |
| 501 | self.assertEqual(displayname, last_crumb.text) |
| 502 | |
| 503 | @@ -60,9 +56,7 @@ |
| 504 | distribution=self.distribution, |
| 505 | displayname=None, |
| 506 | http_url=http_url) |
| 507 | - crumbs = self._getBreadcrumbs( |
| 508 | - canonical_url(mirror), |
| 509 | - [self.root, self.distribution, mirror]) |
| 510 | + crumbs = self.getBreadcrumbsForObject(mirror) |
| 511 | last_crumb = crumbs[-1] |
| 512 | self.assertEqual("Example.com-archive", last_crumb.text) |
| 513 | |
| 514 | @@ -74,9 +68,7 @@ |
| 515 | distribution=self.distribution, |
| 516 | displayname=None, |
| 517 | ftp_url=ftp_url) |
| 518 | - crumbs = self._getBreadcrumbs( |
| 519 | - canonical_url(mirror), |
| 520 | - [self.root, self.distribution, mirror]) |
| 521 | + crumbs = self.getBreadcrumbsForObject(mirror) |
| 522 | last_crumb = crumbs[-1] |
| 523 | self.assertEqual("Example.com-archive", last_crumb.text) |
| 524 | |
| 525 | @@ -93,15 +85,13 @@ |
| 526 | self.milestone_url = canonical_url(self.milestone) |
| 527 | |
| 528 | def test_milestone_without_code_name(self): |
| 529 | - crumbs = self._getBreadcrumbs( |
| 530 | - self.milestone_url, [self.root, self.project, self.milestone]) |
| 531 | + crumbs = self.getBreadcrumbsForObject(self.milestone) |
| 532 | last_crumb = crumbs[-1] |
| 533 | self.assertEqual(self.milestone.name, last_crumb.text) |
| 534 | |
| 535 | def test_milestone_with_code_name(self): |
| 536 | self.milestone.code_name = "duck" |
| 537 | - crumbs = self._getBreadcrumbs( |
| 538 | - self.milestone_url, [self.root, self.project, self.milestone]) |
| 539 | + crumbs = self.getBreadcrumbsForObject(self.milestone) |
| 540 | last_crumb = crumbs[-1] |
| 541 | expected_text = '%s "%s"' % ( |
| 542 | self.milestone.name, self.milestone.code_name) |
| 543 | @@ -109,10 +99,7 @@ |
| 544 | |
| 545 | def test_productrelease(self): |
| 546 | release = self.factory.makeProductRelease(milestone=self.milestone) |
| 547 | - self.release_url = canonical_url(release) |
| 548 | - crumbs = self._getBreadcrumbs( |
| 549 | - self.release_url, |
| 550 | - [self.root, self.project, self.series, self.milestone]) |
| 551 | + crumbs = self.getBreadcrumbsForObject(release) |
| 552 | last_crumb = crumbs[-1] |
| 553 | self.assertEqual(self.milestone.name, last_crumb.text) |
| 554 | |
| 555 | @@ -131,12 +118,9 @@ |
| 556 | name=name, |
| 557 | title=title, |
| 558 | proposition=proposition) |
| 559 | - self.poll_url = canonical_url(self.poll) |
| 560 | |
| 561 | def test_poll(self): |
| 562 | - crumbs = self._getBreadcrumbs( |
| 563 | - self.poll_url, |
| 564 | - [self.root, self.team, self.poll]) |
| 565 | + crumbs = self.getBreadcrumbsForObject(self.poll) |
| 566 | last_crumb = crumbs[-1] |
| 567 | self.assertEqual(self.poll.title, last_crumb.text) |
| 568 | |
| 569 | |
| 570 | === modified file 'lib/lp/soyuz/browser/tests/test_breadcrumbs.py' |
| 571 | --- lib/lp/soyuz/browser/tests/test_breadcrumbs.py 2009-09-29 07:21:40 +0000 |
| 572 | +++ lib/lp/soyuz/browser/tests/test_breadcrumbs.py 2010-04-28 21:41:35 +0000 |
| 573 | @@ -8,11 +8,11 @@ |
| 574 | from zope.component import getUtility |
| 575 | |
| 576 | from canonical.launchpad.webapp.publisher import canonical_url |
| 577 | -from canonical.launchpad.webapp.tests.breadcrumbs import ( |
| 578 | - BaseBreadcrumbTestCase) |
| 579 | + |
| 580 | from lp.registry.interfaces.distribution import IDistributionSet |
| 581 | from lp.soyuz.browser.archivesubscription import PersonalArchiveSubscription |
| 582 | from lp.testing import login, login_person |
| 583 | +from lp.testing.breadcrumbs import BaseBreadcrumbTestCase |
| 584 | |
| 585 | |
| 586 | class TestDistroArchSeriesBreadcrumb(BaseBreadcrumbTestCase): |
| 587 | @@ -22,39 +22,27 @@ |
| 588 | self.ubuntu = getUtility(IDistributionSet).getByName('ubuntu') |
| 589 | self.hoary = self.ubuntu.getSeries('hoary') |
| 590 | self.hoary_i386 = self.hoary['i386'] |
| 591 | - self.traversed_objects = [ |
| 592 | - self.root, self.ubuntu, self.hoary, self.hoary_i386] |
| 593 | |
| 594 | def test_distroarchseries(self): |
| 595 | das_url = canonical_url(self.hoary_i386) |
| 596 | - urls = self._getBreadcrumbsURLs(das_url, self.traversed_objects) |
| 597 | - texts = self._getBreadcrumbsTexts(das_url, self.traversed_objects) |
| 598 | - |
| 599 | - self.assertEquals(urls[-1], das_url) |
| 600 | - self.assertEquals(texts[-1], "i386") |
| 601 | + crumbs = self.getBreadcrumbsForObject(self.hoary_i386) |
| 602 | + self.assertEquals(crumbs[-1].url, das_url) |
| 603 | + self.assertEquals(crumbs[-1].text, "i386") |
| 604 | |
| 605 | def test_distroarchseriesbinarypackage(self): |
| 606 | pmount_hoary_i386 = self.hoary_i386.getBinaryPackage("pmount") |
| 607 | - self.traversed_objects.append(pmount_hoary_i386) |
| 608 | pmount_url = canonical_url(pmount_hoary_i386) |
| 609 | - urls = self._getBreadcrumbsURLs(pmount_url, self.traversed_objects) |
| 610 | - texts = self._getBreadcrumbsTexts(pmount_url, self.traversed_objects) |
| 611 | - |
| 612 | - self.assertEquals(urls[-1], pmount_url) |
| 613 | - self.assertEquals(texts[-1], "pmount") |
| 614 | + crumbs = self.getBreadcrumbsForObject(pmount_hoary_i386) |
| 615 | + self.assertEquals(crumbs[-1].url, pmount_url) |
| 616 | + self.assertEquals(crumbs[-1].text, "pmount") |
| 617 | |
| 618 | def test_distroarchseriesbinarypackagerelease(self): |
| 619 | pmount_hoary_i386 = self.hoary_i386.getBinaryPackage("pmount") |
| 620 | pmount_release = pmount_hoary_i386['0.1-1'] |
| 621 | - self.traversed_objects.extend([pmount_hoary_i386, pmount_release]) |
| 622 | pmount_release_url = canonical_url(pmount_release) |
| 623 | - urls = self._getBreadcrumbsURLs( |
| 624 | - pmount_release_url, self.traversed_objects) |
| 625 | - texts = self._getBreadcrumbsTexts( |
| 626 | - pmount_release_url, self.traversed_objects) |
| 627 | - |
| 628 | - self.assertEquals(urls[-1], pmount_release_url) |
| 629 | - self.assertEquals(texts[-1], "0.1-1") |
| 630 | + crumbs = self.getBreadcrumbsForObject(pmount_release) |
| 631 | + self.assertEquals(crumbs[-1].url, pmount_release_url) |
| 632 | + self.assertEquals(crumbs[-1].text, "0.1-1") |
| 633 | |
| 634 | |
| 635 | class TestArchiveSubscriptionBreadcrumb(BaseBreadcrumbTestCase): |
| 636 | @@ -76,18 +64,10 @@ |
| 637 | owner, self.ppa) |
| 638 | |
| 639 | def test_personal_archive_subscription(self): |
| 640 | - self.traversed_objects = [ |
| 641 | - self.root, self.ppa.owner, self.personal_archive_subscription] |
| 642 | subscription_url = canonical_url(self.personal_archive_subscription) |
| 643 | - |
| 644 | - urls = self._getBreadcrumbsURLs( |
| 645 | - subscription_url, self.traversed_objects) |
| 646 | - texts = self._getBreadcrumbsTexts( |
| 647 | - subscription_url, self.traversed_objects) |
| 648 | - |
| 649 | - self.assertEquals(subscription_url, urls[-1]) |
| 650 | - self.assertEquals( |
| 651 | - "Access to %s" % self.ppa.displayname, texts[-1]) |
| 652 | + crumbs = self.getBreadcrumbsForObject(self.personal_archive_subscription) |
| 653 | + self.assertEquals(subscription_url, crumbs[-1].url) |
| 654 | + self.assertEquals("Access to %s" % self.ppa.displayname, crumbs[-1].text) |
| 655 | |
| 656 | def test_suite(): |
| 657 | return unittest.TestLoader().loadTestsFromName(__name__) |
| 658 | |
| 659 | === renamed file 'lib/canonical/launchpad/webapp/tests/breadcrumbs.py' => 'lib/lp/testing/breadcrumbs.py' |
| 660 | --- lib/canonical/launchpad/webapp/tests/breadcrumbs.py 2009-09-17 18:05:29 +0000 |
| 661 | +++ lib/lp/testing/breadcrumbs.py 2010-04-28 21:41:35 +0000 |
| 662 | @@ -3,67 +3,51 @@ |
| 663 | |
| 664 | __metaclass__ = type |
| 665 | |
| 666 | -from zope.app import zapi |
| 667 | -from zope.component import ComponentLookupError, getMultiAdapter |
| 668 | - |
| 669 | -from canonical.lazr.testing.menus import make_fake_request |
| 670 | -from canonical.launchpad.layers import setFirstLayer |
| 671 | -from canonical.launchpad.webapp.publisher import RootObject |
| 672 | +from canonical.launchpad.webapp.publisher import canonical_url |
| 673 | from canonical.testing import DatabaseFunctionalLayer |
| 674 | + |
| 675 | from lp.testing import TestCaseWithFactory |
| 676 | +from lp.testing.views import create_initialized_view |
| 677 | +from lp.testing.publication import test_traverse |
| 678 | |
| 679 | |
| 680 | class BaseBreadcrumbTestCase(TestCaseWithFactory): |
| 681 | |
| 682 | layer = DatabaseFunctionalLayer |
| 683 | - request_layer = None |
| 684 | - |
| 685 | - def setUp(self): |
| 686 | - super(BaseBreadcrumbTestCase, self).setUp() |
| 687 | - self.root = RootObject() |
| 688 | - |
| 689 | - def _getHierarchyView(self, url, traversed_objects): |
| 690 | - request = self._make_request(url, traversed_objects) |
| 691 | - return getMultiAdapter((self.root, request), name='+hierarchy') |
| 692 | - |
| 693 | - def _getBreadcrumbs(self, url, traversed_objects): |
| 694 | - view = self._getHierarchyView(url, traversed_objects) |
| 695 | + |
| 696 | + def assertBreadcrumbs(self, expected, obj, view_name=None, rootsite=None): |
| 697 | + """Assert that the breadcrumbs for obj match the expected values. |
| 698 | + |
| 699 | + :param expected: A list of tuples containing (text, url) pairs. |
| 700 | + """ |
| 701 | + crumbs = self.getBreadcrumbsForObject(obj, view_name, rootsite) |
| 702 | + self.assertEqual( |
| 703 | + expected, |
| 704 | + [(crumb.text, crumb.url) for crumb in crumbs]) |
| 705 | + |
| 706 | + def assertBreadcrumbTexts(self, expected, obj, view_name=None, |
| 707 | + rootsite=None): |
| 708 | + """The text of the breadcrumbs for obj match the expected values.""" |
| 709 | + crumbs = self.getBreadcrumbsForObject(obj, view_name, rootsite) |
| 710 | + self.assertEqual(expected, [crumb.text for crumb in crumbs]) |
| 711 | + |
| 712 | + def assertBreadcrumbUrls(self, expected, obj, view_name=None, |
| 713 | + rootsite=None): |
| 714 | + """The urls of the breadcrumbs for obj match the expected values.""" |
| 715 | + crumbs = self.getBreadcrumbsForObject(obj, view_name, rootsite) |
| 716 | + self.assertEqual(expected, [crumb.url for crumb in crumbs]) |
| 717 | + |
| 718 | + def getBreadcrumbsForObject(self, obj, view_name=None, rootsite=None): |
| 719 | + """Get the breadcrumbs for the specified object. |
| 720 | + |
| 721 | + Traverse to the canonical_url of the object, and use the request from |
| 722 | + that to feed into the initialized hierarchy view so we get the |
| 723 | + traversed objects. |
| 724 | + """ |
| 725 | + url = canonical_url(obj, view_name=view_name, rootsite=rootsite) |
| 726 | + return self.getBreadcrumbsForUrl(url) |
| 727 | + |
| 728 | + def getBreadcrumbsForUrl(self, url): |
| 729 | + obj, view, request = test_traverse(url) |
| 730 | + view = create_initialized_view(obj, '+hierarchy', request=request) |
| 731 | return view.items |
| 732 | - |
| 733 | - def _getBreadcrumbsTexts(self, url, traversed_objects): |
| 734 | - crumbs = self._getBreadcrumbs(url, traversed_objects) |
| 735 | - return [crumb.text for crumb in crumbs] |
| 736 | - |
| 737 | - def _getBreadcrumbsURLs(self, url, traversed_objects): |
| 738 | - crumbs = self._getBreadcrumbs(url, traversed_objects) |
| 739 | - return [crumb.url for crumb in crumbs] |
| 740 | - |
| 741 | - def _make_request(self, url, traversed_objects): |
| 742 | - """Create and return a LaunchpadTestRequest. |
| 743 | - |
| 744 | - Set the given list of traversed objects as request.traversed_objects, |
| 745 | - also appending the view that the given URL points to, to mimic how |
| 746 | - request.traversed_objects behave in a real request. |
| 747 | - |
| 748 | - XXX: salgado, bug=432025, 2009-09-17: Instead of setting |
| 749 | - request.traversed_objects manually, we should duplicate parts of |
| 750 | - zope.publisher.publish.publish here (or in make_fake_request()) so |
| 751 | - that tests don't have to specify the list of traversed objects for us |
| 752 | - to set here. |
| 753 | - """ |
| 754 | - request = make_fake_request(url, traversed_objects=traversed_objects) |
| 755 | - if self.request_layer is not None: |
| 756 | - setFirstLayer(request, self.request_layer) |
| 757 | - last_segment = request._traversed_names[-1] |
| 758 | - if traversed_objects: |
| 759 | - obj = traversed_objects[-1] |
| 760 | - # Assume the last_segment is the name of the view on the last |
| 761 | - # traversed object, and if we fail to find a view with that name, |
| 762 | - # use the default view. |
| 763 | - try: |
| 764 | - view = getMultiAdapter((obj, request), name=last_segment) |
| 765 | - except ComponentLookupError: |
| 766 | - default_view_name = zapi.getDefaultViewName(obj, request) |
| 767 | - view = getMultiAdapter((obj, request), name=default_view_name) |
| 768 | - request.traversed_objects.append(view) |
| 769 | - return request |
| 770 | |
| 771 | === modified file 'lib/lp/testing/publication.py' |
| 772 | --- lib/lp/testing/publication.py 2009-07-17 02:25:09 +0000 |
| 773 | +++ lib/lp/testing/publication.py 2010-04-28 21:41:35 +0000 |
| 774 | @@ -7,14 +7,24 @@ |
| 775 | __all__ = [ |
| 776 | 'get_request_and_publication', |
| 777 | 'print_request_and_publication', |
| 778 | + 'test_traverse', |
| 779 | ] |
| 780 | |
| 781 | from cStringIO import StringIO |
| 782 | |
| 783 | # Z3 doesn't make this available as a utility. |
| 784 | +from zope.app import zapi |
| 785 | from zope.app.publication.requestpublicationregistry import factoryRegistry |
| 786 | +from zope.component import getUtility |
| 787 | +from zope.interface import providedBy |
| 788 | +from zope.publisher.interfaces.browser import IDefaultSkin |
| 789 | + |
| 790 | +from canonical.launchpad.interfaces.launchpad import IOpenLaunchBag |
| 791 | +import canonical.launchpad.layers as layers |
| 792 | +from canonical.launchpad.webapp import urlsplit |
| 793 | from canonical.launchpad.webapp.servers import ProtocolErrorPublication |
| 794 | |
| 795 | + |
| 796 | # Defines an helper function that returns the appropriate |
| 797 | # IRequest and IPublication. |
| 798 | def get_request_and_publication(host='localhost', port=None, |
| 799 | @@ -39,6 +49,7 @@ |
| 800 | publication = publication_factory(None) |
| 801 | return request, publication |
| 802 | |
| 803 | + |
| 804 | def print_request_and_publication(host='localhost', port=None, |
| 805 | method='GET', |
| 806 | mime_type='text/html', |
| 807 | @@ -56,3 +67,49 @@ |
| 808 | print " %s: %s" % (name, value) |
| 809 | else: |
| 810 | print publication_classname |
| 811 | + |
| 812 | + |
| 813 | +def test_traverse(url): |
| 814 | + """Traverse the url in the same way normal publishing occurs. |
| 815 | + |
| 816 | + Returns a tuple of (object, view, request) where: |
| 817 | + object is the last model object in the traversal chain |
| 818 | + view is the defined view for the object at the specified url (if |
| 819 | + the url didn't directly specify a view, then the view is the |
| 820 | + default view for the object. |
| 821 | + request is the request object resulting from the traversal. This |
| 822 | + contains a populated traversed_objects list just as a browser |
| 823 | + request would from a normal call into the app servers. |
| 824 | + |
| 825 | + This call uses the currently logged in user, and does not start a new |
| 826 | + transaction. |
| 827 | + """ |
| 828 | + url_parts = urlsplit(url) |
| 829 | + server_url = '://'.join(url_parts[0:2]) |
| 830 | + path_info = url_parts[2] |
| 831 | + request, publication = get_request_and_publication( |
| 832 | + host=url_parts[1], extra_environment={ |
| 833 | + 'SERVER_URL': server_url, |
| 834 | + 'PATH_INFO': path_info}) |
| 835 | + |
| 836 | + request.setPublication(publication) |
| 837 | + # We avoid calling publication.beforePublication because this starts a new |
| 838 | + # transaction, which causes an abort of the existing transaction, and the |
| 839 | + # removal of any created and uncommitted objects. |
| 840 | + |
| 841 | + # Set the default layer. |
| 842 | + adapters = zapi.getGlobalSiteManager().adapters |
| 843 | + layer = adapters.lookup((providedBy(request),), IDefaultSkin, '') |
| 844 | + if layer is not None: |
| 845 | + layers.setAdditionalLayer(request, layer) |
| 846 | + |
| 847 | + principal = publication.getPrincipal(request) |
| 848 | + request.setPrincipal(principal) |
| 849 | + |
| 850 | + getUtility(IOpenLaunchBag).clear() |
| 851 | + app = publication.getApplication(request) |
| 852 | + view = request.traverse(app) |
| 853 | + # Since the last traversed object is the view, the second last should be |
| 854 | + # the object that the view is on. |
| 855 | + obj = request.traversed_objects[-2] |
| 856 | + return obj, view, request |
| 857 | |
| 858 | === modified file 'lib/lp/translations/browser/tests/test_breadcrumbs.py' |
| 859 | --- lib/lp/translations/browser/tests/test_breadcrumbs.py 2009-11-07 01:45:32 +0000 |
| 860 | +++ lib/lp/translations/browser/tests/test_breadcrumbs.py 2010-04-28 21:41:35 +0000 |
| 861 | @@ -7,12 +7,8 @@ |
| 862 | |
| 863 | from canonical.lazr.utils import smartquote |
| 864 | |
| 865 | -from canonical.launchpad.layers import TranslationsLayer |
| 866 | -from canonical.launchpad.webapp.publisher import canonical_url |
| 867 | -from canonical.launchpad.webapp.tests.breadcrumbs import ( |
| 868 | - BaseBreadcrumbTestCase) |
| 869 | - |
| 870 | from lp.services.worlddata.interfaces.language import ILanguageSet |
| 871 | +from lp.testing.breadcrumbs import BaseBreadcrumbTestCase |
| 872 | from lp.translations.interfaces.distroserieslanguage import ( |
| 873 | IDistroSeriesLanguageSet) |
| 874 | from lp.translations.interfaces.productserieslanguage import ( |
| 875 | @@ -20,111 +16,82 @@ |
| 876 | from lp.translations.interfaces.translationgroup import ITranslationGroupSet |
| 877 | |
| 878 | |
| 879 | -class BaseTranslationsBreadcrumbTestCase(BaseBreadcrumbTestCase): |
| 880 | - request_layer = TranslationsLayer |
| 881 | - |
| 882 | - def setUp(self): |
| 883 | - super(BaseTranslationsBreadcrumbTestCase, self).setUp() |
| 884 | - self.traversed_objects = [self.root] |
| 885 | - |
| 886 | - def _testContextBreadcrumbs(self, traversal_list, links, texts, url=None): |
| 887 | - self.traversed_objects.extend(traversal_list) |
| 888 | - if url is None: |
| 889 | - url = canonical_url(traversal_list[-1], rootsite='translations') |
| 890 | - |
| 891 | - self.assertEquals( |
| 892 | - links, |
| 893 | - self._getBreadcrumbsURLs(url, self.traversed_objects)) |
| 894 | - self.assertEquals( |
| 895 | - texts, |
| 896 | - self._getBreadcrumbsTexts(url, self.traversed_objects)) |
| 897 | - |
| 898 | - |
| 899 | -class TestTranslationsVHostBreadcrumb(BaseTranslationsBreadcrumbTestCase): |
| 900 | +class TestTranslationsVHostBreadcrumb(BaseBreadcrumbTestCase): |
| 901 | |
| 902 | def test_product(self): |
| 903 | product = self.factory.makeProduct( |
| 904 | name='crumb-tester', displayname="Crumb Tester") |
| 905 | - self._testContextBreadcrumbs( |
| 906 | - [product], |
| 907 | - ['http://launchpad.dev/crumb-tester', |
| 908 | - 'http://translations.launchpad.dev/crumb-tester'], |
| 909 | - ["Crumb Tester", "Translations"]) |
| 910 | + self.assertBreadcrumbs( |
| 911 | + [("Crumb Tester", 'http://launchpad.dev/crumb-tester'), |
| 912 | + ("Translations", 'http://translations.launchpad.dev/crumb-tester')], |
| 913 | + product, rootsite='translations') |
| 914 | |
| 915 | def test_productseries(self): |
| 916 | product = self.factory.makeProduct( |
| 917 | name='crumb-tester', displayname="Crumb Tester") |
| 918 | series = self.factory.makeProductSeries(name="test", product=product) |
| 919 | - self._testContextBreadcrumbs( |
| 920 | - [product, series], |
| 921 | - ['http://launchpad.dev/crumb-tester', |
| 922 | - 'http://launchpad.dev/crumb-tester/test', |
| 923 | - 'http://translations.launchpad.dev/crumb-tester/test'], |
| 924 | - ["Crumb Tester", "Series test", "Translations"]) |
| 925 | + self.assertBreadcrumbs( |
| 926 | + [("Crumb Tester", 'http://launchpad.dev/crumb-tester'), |
| 927 | + ("Series test", 'http://launchpad.dev/crumb-tester/test'), |
| 928 | + ("Translations", 'http://translations.launchpad.dev/crumb-tester/test')], |
| 929 | + series, rootsite='translations') |
| 930 | |
| 931 | def test_distribution(self): |
| 932 | distribution = self.factory.makeDistribution( |
| 933 | name='crumb-tester', displayname="Crumb Tester") |
| 934 | - self._testContextBreadcrumbs( |
| 935 | - [distribution], |
| 936 | - ['http://launchpad.dev/crumb-tester', |
| 937 | - 'http://translations.launchpad.dev/crumb-tester'], |
| 938 | - ["Crumb Tester", "Translations"]) |
| 939 | + self.assertBreadcrumbs( |
| 940 | + [("Crumb Tester", 'http://launchpad.dev/crumb-tester'), |
| 941 | + ("Translations", 'http://translations.launchpad.dev/crumb-tester')], |
| 942 | + distribution, rootsite='translations') |
| 943 | |
| 944 | def test_distroseries(self): |
| 945 | distribution = self.factory.makeDistribution( |
| 946 | name='crumb-tester', displayname="Crumb Tester") |
| 947 | series = self.factory.makeDistroRelease( |
| 948 | name="test", version="1.0", distribution=distribution) |
| 949 | - self._testContextBreadcrumbs( |
| 950 | - [distribution, series], |
| 951 | - ['http://launchpad.dev/crumb-tester', |
| 952 | - 'http://launchpad.dev/crumb-tester/test', |
| 953 | - 'http://translations.launchpad.dev/crumb-tester/test'], |
| 954 | - ["Crumb Tester", "Test (1.0)", "Translations"]) |
| 955 | + self.assertBreadcrumbs( |
| 956 | + [("Crumb Tester", 'http://launchpad.dev/crumb-tester'), |
| 957 | + ("Test (1.0)", 'http://launchpad.dev/crumb-tester/test'), |
| 958 | + ("Translations", 'http://translations.launchpad.dev/crumb-tester/test')], |
| 959 | + series, rootsite='translations') |
| 960 | |
| 961 | def test_project(self): |
| 962 | project = self.factory.makeProject( |
| 963 | name='crumb-tester', displayname="Crumb Tester") |
| 964 | - self._testContextBreadcrumbs( |
| 965 | - [project], |
| 966 | - ['http://launchpad.dev/crumb-tester', |
| 967 | - 'http://translations.launchpad.dev/crumb-tester'], |
| 968 | - ["Crumb Tester", "Translations"]) |
| 969 | + self.assertBreadcrumbs( |
| 970 | + [("Crumb Tester", 'http://launchpad.dev/crumb-tester'), |
| 971 | + ("Translations", 'http://translations.launchpad.dev/crumb-tester')], |
| 972 | + project, rootsite='translations') |
| 973 | |
| 974 | def test_person(self): |
| 975 | person = self.factory.makePerson( |
| 976 | name='crumb-tester', displayname="Crumb Tester") |
| 977 | - self._testContextBreadcrumbs( |
| 978 | - [person], |
| 979 | - ['http://launchpad.dev/~crumb-tester', |
| 980 | - 'http://translations.launchpad.dev/~crumb-tester'], |
| 981 | - ["Crumb Tester", "Translations"]) |
| 982 | - |
| 983 | - |
| 984 | -class TestTranslationGroupsBreadcrumbs(BaseTranslationsBreadcrumbTestCase): |
| 985 | + self.assertBreadcrumbs( |
| 986 | + [("Crumb Tester", 'http://launchpad.dev/~crumb-tester'), |
| 987 | + ("Translations", 'http://translations.launchpad.dev/~crumb-tester')], |
| 988 | + person, rootsite='translations') |
| 989 | + |
| 990 | + |
| 991 | +class TestTranslationGroupsBreadcrumbs(BaseBreadcrumbTestCase): |
| 992 | |
| 993 | def test_translationgroupset(self): |
| 994 | group_set = getUtility(ITranslationGroupSet) |
| 995 | - url = canonical_url(group_set, rootsite='translations') |
| 996 | - self._testContextBreadcrumbs( |
| 997 | - [group_set], |
| 998 | - ['http://translations.launchpad.dev/+groups'], |
| 999 | - ['Translation groups'], |
| 1000 | - url=url) |
| 1001 | + self.assertBreadcrumbs( |
| 1002 | + [("Translation groups", 'http://translations.launchpad.dev/+groups')], |
| 1003 | + group_set, rootsite='translations') |
| 1004 | |
| 1005 | def test_translationgroup(self): |
| 1006 | - group_set = getUtility(ITranslationGroupSet) |
| 1007 | group = self.factory.makeTranslationGroup( |
| 1008 | name='test-translators', title='Test translators') |
| 1009 | - self._testContextBreadcrumbs( |
| 1010 | - [group_set, group], |
| 1011 | - ["http://translations.launchpad.dev/+groups", |
| 1012 | - "http://translations.launchpad.dev/+groups/test-translators"], |
| 1013 | - ["Translation groups", "Test translators"]) |
| 1014 | - |
| 1015 | - |
| 1016 | -class TestSeriesLanguageBreadcrumbs(BaseTranslationsBreadcrumbTestCase): |
| 1017 | + self.assertBreadcrumbs( |
| 1018 | + [("Translation groups", 'http://translations.launchpad.dev/+groups'), |
| 1019 | + ("Test translators", |
| 1020 | + 'http://translations.launchpad.dev/+groups/test-translators')], |
| 1021 | + group, rootsite='translations') |
| 1022 | + |
| 1023 | + |
| 1024 | +class TestSeriesLanguageBreadcrumbs(BaseBreadcrumbTestCase): |
| 1025 | + |
| 1026 | def setUp(self): |
| 1027 | super(TestSeriesLanguageBreadcrumbs, self).setUp() |
| 1028 | self.language = getUtility(ILanguageSet)['sr'] |
| 1029 | @@ -134,15 +101,18 @@ |
| 1030 | name='crumb-tester', displayname="Crumb Tester") |
| 1031 | series = self.factory.makeDistroRelease( |
| 1032 | name="test", version="1.0", distribution=distribution) |
| 1033 | + series.hide_all_translations = False |
| 1034 | serieslanguage = getUtility(IDistroSeriesLanguageSet).getDummy( |
| 1035 | series, self.language) |
| 1036 | - self._testContextBreadcrumbs( |
| 1037 | - [distribution, series, serieslanguage], |
| 1038 | - ["http://launchpad.dev/crumb-tester", |
| 1039 | - "http://launchpad.dev/crumb-tester/test", |
| 1040 | - "http://translations.launchpad.dev/crumb-tester/test", |
| 1041 | - "http://translations.launchpad.dev/crumb-tester/test/+lang/sr"], |
| 1042 | - ["Crumb Tester", "Test (1.0)", "Translations", "Serbian (sr)"]) |
| 1043 | + |
| 1044 | + self.assertBreadcrumbs( |
| 1045 | + [("Crumb Tester", "http://launchpad.dev/crumb-tester"), |
| 1046 | + ("Test (1.0)", "http://launchpad.dev/crumb-tester/test"), |
| 1047 | + ("Translations", |
| 1048 | + "http://translations.launchpad.dev/crumb-tester/test"), |
| 1049 | + ("Serbian (sr)", |
| 1050 | + "http://translations.launchpad.dev/crumb-tester/test/+lang/sr")], |
| 1051 | + serieslanguage) |
| 1052 | |
| 1053 | def test_productserieslanguage(self): |
| 1054 | product = self.factory.makeProduct( |
| 1055 | @@ -151,57 +121,58 @@ |
| 1056 | name="test", product=product) |
| 1057 | serieslanguage = getUtility(IProductSeriesLanguageSet).getDummy( |
| 1058 | series, self.language) |
| 1059 | - self._testContextBreadcrumbs( |
| 1060 | - [product, series, serieslanguage], |
| 1061 | - ["http://launchpad.dev/crumb-tester", |
| 1062 | - "http://launchpad.dev/crumb-tester/test", |
| 1063 | - "http://translations.launchpad.dev/crumb-tester/test", |
| 1064 | - "http://translations.launchpad.dev/crumb-tester/test/+lang/sr"], |
| 1065 | - ["Crumb Tester", "Series test", "Translations", "Serbian (sr)"]) |
| 1066 | - |
| 1067 | - |
| 1068 | -class TestPOTemplateBreadcrumbs(BaseTranslationsBreadcrumbTestCase): |
| 1069 | + |
| 1070 | + self.assertBreadcrumbs( |
| 1071 | + [("Crumb Tester", "http://launchpad.dev/crumb-tester"), |
| 1072 | + ("Series test", "http://launchpad.dev/crumb-tester/test"), |
| 1073 | + ("Translations", |
| 1074 | + "http://translations.launchpad.dev/crumb-tester/test"), |
| 1075 | + ("Serbian (sr)", |
| 1076 | + "http://translations.launchpad.dev/crumb-tester/test/+lang/sr")], |
| 1077 | + serieslanguage) |
| 1078 | + |
| 1079 | + |
| 1080 | +class TestPOTemplateBreadcrumbs(BaseBreadcrumbTestCase): |
| 1081 | def test_potemplate(self): |
| 1082 | product = self.factory.makeProduct( |
| 1083 | - name='crumb-tester', displayname="Crumb Tester") |
| 1084 | + name='crumb-tester', displayname="Crumb Tester", |
| 1085 | + official_rosetta=True) |
| 1086 | series = self.factory.makeProductSeries( |
| 1087 | name="test", product=product) |
| 1088 | - potemplate = self.factory.makePOTemplate(name="template", |
| 1089 | - productseries=series) |
| 1090 | - self._testContextBreadcrumbs( |
| 1091 | - [product, series, potemplate], |
| 1092 | - ["http://launchpad.dev/crumb-tester", |
| 1093 | - "http://launchpad.dev/crumb-tester/test", |
| 1094 | - "http://translations.launchpad.dev/crumb-tester/test", |
| 1095 | - "http://translations.launchpad.dev/crumb-tester/test" |
| 1096 | - "/+pots/template"], |
| 1097 | - ["Crumb Tester", "Series test", "Translations", |
| 1098 | - smartquote('Template "template"')]) |
| 1099 | - |
| 1100 | - |
| 1101 | -class TestPOFileBreadcrumbs(BaseTranslationsBreadcrumbTestCase): |
| 1102 | + potemplate = self.factory.makePOTemplate( |
| 1103 | + name="template", productseries=series) |
| 1104 | + self.assertBreadcrumbs( |
| 1105 | + [("Crumb Tester", "http://launchpad.dev/crumb-tester"), |
| 1106 | + ("Series test", "http://launchpad.dev/crumb-tester/test"), |
| 1107 | + ("Translations", |
| 1108 | + "http://translations.launchpad.dev/crumb-tester/test"), |
| 1109 | + (smartquote('Template "template"'), |
| 1110 | + "http://translations.launchpad.dev/crumb-tester/test/+pots/template")], |
| 1111 | + potemplate) |
| 1112 | + |
| 1113 | + |
| 1114 | +class TestPOFileBreadcrumbs(BaseBreadcrumbTestCase): |
| 1115 | |
| 1116 | def setUp(self): |
| 1117 | super(TestPOFileBreadcrumbs, self).setUp() |
| 1118 | - self.language = getUtility(ILanguageSet)['eo'] |
| 1119 | - self.product = self.factory.makeProduct( |
| 1120 | - name='crumb-tester', displayname="Crumb Tester") |
| 1121 | - self.series = self.factory.makeProductSeries( |
| 1122 | - name="test", product=self.product) |
| 1123 | - self.potemplate = self.factory.makePOTemplate(self.series, |
| 1124 | - name="test-template") |
| 1125 | - self.pofile = self.factory.makePOFile('eo', self.potemplate) |
| 1126 | |
| 1127 | def test_pofiletranslate(self): |
| 1128 | - self._testContextBreadcrumbs( |
| 1129 | - [self.product, self.series, self.potemplate, self.pofile], |
| 1130 | - ["http://launchpad.dev/crumb-tester", |
| 1131 | - "http://launchpad.dev/crumb-tester/test", |
| 1132 | - "http://translations.launchpad.dev/crumb-tester/test", |
| 1133 | - "http://translations.launchpad.dev/crumb-tester/test" |
| 1134 | - "/+pots/test-template", |
| 1135 | - "http://translations.launchpad.dev/crumb-tester/test" |
| 1136 | - "/+pots/test-template/eo", |
| 1137 | - ], |
| 1138 | - ["Crumb Tester", "Series test", "Translations", |
| 1139 | - smartquote('Template "test-template"'), "Esperanto (eo)"]) |
| 1140 | + product = self.factory.makeProduct( |
| 1141 | + name='crumb-tester', displayname="Crumb Tester", |
| 1142 | + official_rosetta=True) |
| 1143 | + series = self.factory.makeProductSeries(name="test", product=product) |
| 1144 | + potemplate = self.factory.makePOTemplate(series, name="test-template") |
| 1145 | + pofile = self.factory.makePOFile('eo', potemplate) |
| 1146 | + |
| 1147 | + self.assertBreadcrumbs( |
| 1148 | + [("Crumb Tester", "http://launchpad.dev/crumb-tester"), |
| 1149 | + ("Series test", "http://launchpad.dev/crumb-tester/test"), |
| 1150 | + ("Translations", |
| 1151 | + "http://translations.launchpad.dev/crumb-tester/test"), |
| 1152 | + (smartquote('Template "test-template"'), |
| 1153 | + "http://translations.launchpad.dev/crumb-tester/test" |
| 1154 | + "/+pots/test-template"), |
| 1155 | + ("Esperanto (eo)", |
| 1156 | + "http://translations.launchpad.dev/crumb-tester/test" |
| 1157 | + "/+pots/test-template/eo")], |
| 1158 | + pofile) |

Hi Tim,
Hooray for finally battling to success on this :-) Only one mandatory
change: give test_traverse a docstring. Otherwise, it's basically all
good.
> === modified file 'lib/lp/ code/browser/ codeimportmachi ne.py' code/browser/ codeimportmachi ne.py 2009-08-24 20:28:33 +0000 code/browser/ codeimportmachi ne.py 2010-04-28 05:07:44 +0000 ineBreadcrumb' , ineSetBreadcrum b', ineSetNavigatio n', ineSetView' , neBreadcrumb( Breadcrumb) : hostname neSetNavigation (Navigation) : ineSet. """ ineSet
> --- lib/lp/
> +++ lib/lp/
> @@ -6,6 +6,7 @@
> __metaclass__ = type
>
> __all__ = [
> + 'CodeImportMach
> 'CodeImportMach
> 'CodeImportMach
> 'CodeImportMach
> @@ -30,6 +31,14 @@
> from lazr.delegates import delegates
>
>
> +class CodeImportMachi
> + """An `IBreadcrumb` that uses the machines hostname."""
> +
> + @property
> + def text(self):
> + return self.context.
> +
> +
> class CodeImportMachi
> """Navigation methods for ICodeImportMach
> usedfor = ICodeImportMach
> === modified file 'lib/lp/ code/browser/ configure. zcml' code/browser/ configure. zcml 2010-04-19 03:44:27 +0000 code/browser/ configure. zcml 2010-04-28 05:07:44 +0000 code.interfaces .branchmergepro posal.IBranchMe rgeProposal" "lp.code. browser. branchmergeprop osal.BranchMerg eProposalBreadc rumb" "zope.Public" /> "canonical. launchpad. webapp. interfaces. IBreadcrumb" code.interfaces .codeimportmach ine.ICodeImport Machine" "lp.code. browser. codeimportmachi ne.CodeImportMa chineBreadcrumb " "zope.Public" /> "canonical. launchpad. webapp. interfaces. IBreadcrumb" code.interfaces .codeimportmach ine.ICodeImport MachineSet" "lp.code. browser. codeimportmachi ne.CodeImportMa chineSetBreadcr umb" "zope.Public" /> "lp.code. browser. branchmergeprop osal.PreviewDif fHTMLRepresenta tion" restful. EntryResource" />
> --- lib/lp/
> +++ lib/lp/
> @@ -1055,6 +1055,19 @@
> for="lp.
> factory=
> permission=
> +
> + <adapter
> + provides=
> + for="lp.
> + factory=
> + permission=
> +
> + <adapter
> + provides=
> + for="lp.
> + factory=
> + permission=
> +
> <adapter
> factory=
> name="lazr.
This is all you wanted to add to start with, right? :-)
> === renamed file 'lib/canonical/ launchpad/ webapp/ tests/breadcrum bs.py' => 'lib/lp/ testing/ breadcrumbs. py' launchpad/ webapp/ tests/breadcrum bs.py 2009-09-17 18:05:29 +0000 testing/ breadcrumbs. py 2010-04-28 05:07:44 +0000 lazr.testing. menus import make_fake_request launchpad. layers import setFirstLayer launchpad. webapp. publisher import RootObject launchpad. webapp. publisher import canonical_url, RootObject nalLayer initialized_ view publication import test_traverse estCase( TestCaseWithFac tory): crumbTestCase, self).setUp() bs(self, obj, expected):
> --- lib/canonical/
> +++ lib/lp/
> @@ -8,9 +8,12 @@
>
> from canonical.
> from canonical.
> -from canonical.
> +from canonical.
> from canonical.testing import DatabaseFunctio
> +
> from lp.testing import TestCaseWithFactory
> +from lp.testing.views import create_
> +from lp.testing.
>
>
> class BaseBreadcrumbT
> @@ -22,9 +25,41 @@
> super(BaseBread
> self.root = RootObject()
>
> + def assertBreadcrum
> + """As...