def test_cssClasses_git(self): # Git diffs look slightly different, so check that they also end up # with the correct CSS classes. diff = dedent('''\ diff --git a/tales.py b/tales.py index aaaaaaa..bbbbbbb 100644 --- a/tales.py +++ b/tales.py @@ -2435,6 +2435,8 @@ def format_diff(self): - removed this line + added this line -------- a sql style comment ++++++++ a line of pluses ''') html = FormattersAPI(diff).format_diff() line_numbers = find_tags_by_class(html, 'line-no') self.assertEqual( ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'], [tag.renderContents() for tag in line_numbers]) text = find_tags_by_class(html, 'text') self.assertEqual( ['diff-file text', 'diff-file text', 'diff-header text', 'diff-header text', 'diff-chunk text', 'text', 'diff-removed text', 'diff-added text', 'diff-removed text', 'diff-added text'], [str(tag['class']) for tag in text])
def test_cssClasses(self): # Different parts of the diff have different css classes. diff = dedent('''\ === modified file 'tales.py' --- tales.py +++ tales.py @@ -2435,6 +2435,8 @@ def format_diff(self): - removed this line + added this line -------- a sql style comment ++++++++ a line of pluses ######## # A merge directive comment. ''') html = FormattersAPI(diff).format_diff() line_numbers = find_tags_by_class(html, 'line-no') self.assertEqual( ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11'], [tag.renderContents() for tag in line_numbers]) text = find_tags_by_class(html, 'text') self.assertEqual( ['diff-file text', 'diff-header text', 'diff-header text', 'diff-chunk text', 'text', 'diff-removed text', 'diff-added text', 'diff-removed text', 'diff-added text', 'diff-comment text', 'diff-comment text'], [str(tag['class']) for tag in text])
def test_cssClasses(self): # Different parts of the diff have different css classes. diff = dedent('''\ === modified file 'tales.py' --- tales.py +++ tales.py @@ -2435,6 +2435,8 @@ def format_diff(self): - removed this line + added this line -------- a sql style comment ++++++++ a line of pluses ######## # A merge directive comment. ''') html = FormattersAPI(diff).format_diff() line_numbers = find_tags_by_class(html, 'line-no') self.assertEqual( ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11'], [tag.renderContents() for tag in line_numbers]) text = find_tags_by_class(html, 'text') self.assertEqual([ 'diff-file text', 'diff-header text', 'diff-header text', 'diff-chunk text', 'text', 'diff-removed text', 'diff-added text', 'diff-removed text', 'diff-added text', 'diff-comment text', 'diff-comment text' ], [str(tag['class']) for tag in text])
def test_redeem_twice_causes_error(self): # If a voucher is redeemed twice, the second attempt is rejected. commercial_admin = login_celebrity('commercial_admin') voucher_id_1, voucher_id_2 = self.makeVouchers(commercial_admin, 2) project_1 = self.factory.makeProduct(name='p1') project_2 = self.factory.makeProduct(name='p2') url = canonical_url(commercial_admin, view_name='+vouchers') browser = self.getUserBrowser(url, commercial_admin) # A second browser opens the +vouchers page before the first browser # attempts to redeem the voucher. browser2 = self.getUserBrowser(url, commercial_admin) browser.getControl( 'Select the project you wish to subscribe').value = 'p1' browser.getControl( 'Select a voucher').getControl(voucher_id_1).selected = True browser.getControl('Redeem').click() with person_logged_in(commercial_admin): self.assertIsNotNone(project_1.commercial_subscription) browser2.getControl( 'Select the project you wish to subscribe').value = 'p2' browser2.getControl( 'Select a voucher').getControl(voucher_id_1).selected = True browser2.getControl('Redeem').click() with person_logged_in(commercial_admin): self.assertIsNone(project_2.commercial_subscription) error_messages = find_tags_by_class(browser2.contents, 'message') self.assertEqual(extract_text(error_messages[1]), 'Invalid value')
def test_basic_for_person(self): """Check that the page shows the bugs/work items assigned to a person. """ person = self.factory.makePerson() workitem = self.factory.makeSpecificationWorkItem( assignee=person, milestone=self.today_milestone) bugtask = self.factory.makeBug( milestone=self.tomorrow_milestone).bugtasks[0] removeSecurityProxy(bugtask).assignee = person browser = self.getViewBrowser( person, view_name='+upcomingwork', no_login=True) # Check that the two work items created above are shown and grouped # under the appropriate milestone date. groups = find_tags_by_class(browser.contents, 'workitems-group') self.assertEqual(2, len(groups)) todays_group = extract_text(groups[0]) tomorrows_group = extract_text(groups[1]) self.assertStartsWith( todays_group, 'Work items due in %s' % self.today) self.assertIn(workitem.title, todays_group) self.assertStartsWith( tomorrows_group, 'Work items due in %s' % self.tomorrow) with anonymous_logged_in(): self.assertIn(bugtask.bug.title, tomorrows_group)
def test_redeem_twice_causes_error(self): # If a voucher is redeemed twice, the second attempt is rejected. commercial_admin = login_celebrity('commercial_admin') voucher_id_1, voucher_id_2 = self.makeVouchers(commercial_admin, 2) project_1 = self.factory.makeProduct(name='p1') project_2 = self.factory.makeProduct(name='p2') url = canonical_url(commercial_admin, view_name='+vouchers') browser = self.getUserBrowser(url, commercial_admin) # A second browser opens the +vouchers page before the first browser # attempts to redeem the voucher. browser2 = self.getUserBrowser(url, commercial_admin) browser.getControl( 'Select the project you wish to subscribe').value = 'p1' browser.getControl('Select a voucher').getControl( voucher_id_1).selected = True browser.getControl('Redeem').click() with person_logged_in(commercial_admin): self.assertIsNotNone(project_1.commercial_subscription) browser2.getControl( 'Select the project you wish to subscribe').value = 'p2' browser2.getControl('Select a voucher').getControl( voucher_id_1).selected = True browser2.getControl('Redeem').click() with person_logged_in(commercial_admin): self.assertIsNone(project_2.commercial_subscription) error_messages = find_tags_by_class(browser2.contents, 'message') self.assertEqual(extract_text(error_messages[1]), 'Invalid value')
def test_basic_for_team(self): """Check that the page shows the bugs/work items assigned to members of a team. """ workitem1 = self.factory.makeSpecificationWorkItem( assignee=self.team.teamowner, milestone=self.today_milestone) workitem2 = self.factory.makeSpecificationWorkItem( assignee=self.team.teamowner, milestone=self.tomorrow_milestone) bugtask1 = self.factory.makeBug( milestone=self.today_milestone).bugtasks[0] bugtask2 = self.factory.makeBug( milestone=self.tomorrow_milestone).bugtasks[0] for bugtask in [bugtask1, bugtask2]: removeSecurityProxy(bugtask).assignee = self.team.teamowner browser = self.getViewBrowser( self.team, view_name='+upcomingwork', no_login=True) # Check that the two work items and bugtasks created above are shown # and grouped under the appropriate milestone date. groups = find_tags_by_class(browser.contents, 'workitems-group') self.assertEqual(2, len(groups)) todays_group = extract_text(groups[0]) tomorrows_group = extract_text(groups[1]) self.assertStartsWith( todays_group, 'Work items due in %s' % self.today) self.assertIn(workitem1.title, todays_group) with anonymous_logged_in(): self.assertIn(bugtask1.bug.title, todays_group) self.assertStartsWith( tomorrows_group, 'Work items due in %s' % self.tomorrow) self.assertIn(workitem2.title, tomorrows_group) with anonymous_logged_in(): self.assertIn(bugtask2.bug.title, tomorrows_group)
def test_replay_attacks_do_not_succeed(self): browser = Browser(mech_browser=MyMechanizeBrowser()) browser.open('%s/+login' % self.layer.appserver_root_url()) # On a JS-enabled browser this page would've been auto-submitted # (thanks to the onload handler), but here we have to do it manually. self.assertIn('body onload', browser.contents) browser.getControl('Continue').click() self.assertEquals('Login', browser.title) fill_login_form_and_submit(browser, '*****@*****.**') login_status = extract_text( find_tag_by_id(browser.contents, 'logincontrol')) self.assertIn('Sample Person (name12)', login_status) # Now we look up (in urls_redirected_to) the +openid-callback URL that # was used to complete the authentication and open it on a different # browser with a fresh set of cookies. replay_browser = Browser() [callback_url] = [ url for url in urls_redirected_to if '+openid-callback' in url] self.assertIsNot(None, callback_url) replay_browser.open(callback_url) login_status = extract_text( find_tag_by_id(replay_browser.contents, 'logincontrol')) self.assertEquals('Log in / Register', login_status) error_msg = find_tags_by_class(replay_browser.contents, 'error')[0] self.assertEquals('Nonce already used or out of range', extract_text(error_msg))
def test_basic_for_person(self): """Check that the page shows the bugs/work items assigned to a person. """ person = self.factory.makePerson() workitem = self.factory.makeSpecificationWorkItem( assignee=person, milestone=self.today_milestone) bugtask = self.factory.makeBug( milestone=self.tomorrow_milestone).bugtasks[0] removeSecurityProxy(bugtask).assignee = person browser = self.getViewBrowser(person, view_name='+upcomingwork', no_login=True) # Check that the two work items created above are shown and grouped # under the appropriate milestone date. groups = find_tags_by_class(browser.contents, 'workitems-group') self.assertEqual(2, len(groups)) todays_group = extract_text(groups[0]) tomorrows_group = extract_text(groups[1]) self.assertStartsWith(todays_group, 'Work items due in %s' % self.today) self.assertIn(workitem.title, todays_group) self.assertStartsWith(tomorrows_group, 'Work items due in %s' % self.tomorrow) with anonymous_logged_in(): self.assertIn(bugtask.bug.title, tomorrows_group)
def print_remote_bugtasks(content): """Print the remote bugtasks of this bug. For each remote bugtask, print the target and the bugwatch. """ affects_table = find_tags_by_class(content, 'listing')[0] for span in affects_table.findAll('span'): for key, value in span.attrs: if 'bug-remote' in value: target = extract_text(span.findAllPrevious('td')[-2]) print target, extract_text(span.findNext('a'))
def test_rescore_build_invalid_score(self): # Build scores can only take numbers. self.build.queueBuild() transaction.commit() browser = self.getViewBrowser(self.build, user=self.buildd_admin) browser.getLink("Rescore build").click() self.assertEqual(self.build_url, browser.getLink("Cancel").url) browser.getControl("Priority").value = "tentwentyfour" browser.getControl("Rescore build").click() self.assertEqual( "Invalid integer data", extract_text(find_tags_by_class(browser.contents, "message")[1]))
def test_distributionsourcepackage_unknown_bugtracker_message(self): # A DistributionSourcePackage whose Distro does not use # Launchpad for bug tracking should explain that. dsp = self._makeDistributionSourcePackage() url = canonical_url(dsp, rootsite='bugs') browser = self.getUserBrowser(url) top_portlet = find_tags_by_class(browser.contents, 'top-portlet') self.assertTrue( len(top_portlet) > 0, "Tag with class=top-portlet not found") self.assertTextMatchesExpressionIgnoreWhitespace( """ test-dsp in Test-distro does not use Launchpad for bug tracking. Getting started with bug tracking in Launchpad.""", extract_text(top_portlet[0]))
def test_store_upload_error_notifies(self): # If a build cannot be scheduled for uploading to the store, we # issue a notification. self.setUpStoreUpload() self.build.updateStatus(BuildStatus.FULLYBUILT) browser = self.getViewBrowser(self.build, user=self.requester) browser.getControl("Upload this package to the store").click() self.assertEqual(self.build_url, browser.url) login(ANONYMOUS) self.assertEqual( [], list(getUtility(ISnapStoreUploadJobSource).iterReady())) self.assertEqual( "Cannot upload this package because it has no files.", extract_text(find_tags_by_class(browser.contents, "message")[0]))
def test_distributionsourcepackage_unknown_bugtracker_message(self): # A DistributionSourcePackage whose Distro does not use # Launchpad for bug tracking should explain that. dsp = self._makeDistributionSourcePackage() url = canonical_url(dsp, rootsite='bugs') browser = self.getUserBrowser(url) top_portlet = find_tags_by_class( browser.contents, 'top-portlet') self.assertTrue(len(top_portlet) > 0, "Tag with class=top-portlet not found") self.assertTextMatchesExpressionIgnoreWhitespace(""" test-dsp in Test-distro does not use Launchpad for bug tracking. Getting started with bug tracking in Launchpad.""", extract_text(top_portlet[0]))
def test_no_xss_on_workitem_title(self): self.factory.makeSpecificationWorkItem( title=u"<script>window.alert('XSS')</script>", assignee=self.team.teamowner, milestone=self.today_milestone) browser = self.getViewBrowser( self.team, view_name='+upcomingwork', no_login=True) groups = find_tags_by_class(browser.contents, 'collapsible-body') self.assertEqual(1, len(groups)) tbody = groups[0] title_td = tbody.findChildren('td')[0] self.assertEqual( "<td>\n<span><script>window.alert('XSS')</script>" "</span>\n</td>", str(title_td))
def test_escaped_message_when_removing_key(self): """Confirm that messages are escaped when removing keys.""" person = self.factory.makePerson() url = '%s/+editsshkeys' % canonical_url(person) public_key = "ssh-rsa %s x<script>alert()</script>example.com" % ( self.getUniqueString()) with person_logged_in(person): # Add the key for the user here, # since we only care about testing removal. getUtility(ISSHKeySet).new(person, public_key) browser = setupBrowserFreshLogin(person) browser.open(url) browser.getControl('Remove').click() msg = 'Key "x<script>alert()</script>example.com" removed' self.assertEqual( extract_text(find_tags_by_class(browser.contents, 'message')[0]), msg)
def test_escaped_message_when_removing_key(self): """Confirm that messages are escaped when removing keys.""" person = self.factory.makePerson() url = '%s/+editsshkeys' % canonical_url(person) public_key = "ssh-rsa %s x<script>alert()</script>example.com" % ( self.getUniqueString()) with person_logged_in(person): # Add the key for the user here, # since we only care about testing removal. getUtility(ISSHKeySet).new(person, public_key) browser = setupBrowserFreshLogin(person) browser.open(url) browser.getControl('Remove').click() msg = 'Key "x<script>alert()</script>example.com" removed' self.assertEqual( extract_text( find_tags_by_class(browser.contents, 'message')[0]), msg)
def test_store_upload(self): # A build not previously uploaded to the store can be uploaded # manually. self.setUpStoreUpload() self.build.updateStatus(BuildStatus.FULLYBUILT) self.factory.makeSnapFile( snapbuild=self.build, libraryfile=self.factory.makeLibraryFileAlias(db_only=True)) browser = self.getViewBrowser(self.build, user=self.requester) browser.getControl("Upload this package to the store").click() self.assertEqual(self.build_url, browser.url) login(ANONYMOUS) [job] = getUtility(ISnapStoreUploadJobSource).iterReady() self.assertEqual(JobStatus.WAITING, job.job.status) self.assertEqual(self.build, job.snapbuild) self.assertEqual( "An upload has been scheduled and will run as soon as possible.", extract_text(find_tags_by_class(browser.contents, "message")[0]))
def test_rescore_build_invalid_score(self): """Build scores can only take numbers.""" queue = self.factory.makeSourcePackageRecipeBuild().queueBuild() build = queue.specific_build transaction.commit() build_url = canonical_url(build) logout() browser = self.getUserBrowser(build_url, user=self.admin) browser.getLink('Rescore build').click() self.assertEqual(browser.getLink('Cancel').url, build_url) browser.getControl('Score').value = 'tentwentyfour' browser.getControl('Rescore build').click() self.assertEqual( extract_text(find_tags_by_class(browser.contents, 'message')[1]), 'Invalid integer data')
def test_store_upload_retry(self): # A build with a previously-failed store upload can have the upload # retried. self.setUpStoreUpload() self.build.updateStatus(BuildStatus.FULLYBUILT) self.factory.makeSnapFile( snapbuild=self.build, libraryfile=self.factory.makeLibraryFileAlias(db_only=True)) old_job = getUtility(ISnapStoreUploadJobSource).create(self.build) removeSecurityProxy(old_job).job._status = JobStatus.FAILED browser = self.getViewBrowser(self.build, user=self.requester) browser.getControl("Retry").click() self.assertEqual(self.build_url, browser.url) login(ANONYMOUS) [job] = getUtility(ISnapStoreUploadJobSource).iterReady() self.assertEqual(JobStatus.WAITING, job.job.status) self.assertEqual(self.build, job.snapbuild) self.assertEqual( "An upload has been scheduled and will run as soon as possible.", extract_text(find_tags_by_class(browser.contents, "message")[0]))
def test_edit_livefs_already_exists(self): distroseries = self.factory.makeDistroSeries( distribution=getUtility(ILaunchpadCelebrities).ubuntu, displayname="Grumpy") livefs = self.factory.makeLiveFS(registrant=self.person, owner=self.person, distroseries=distroseries, name="one") self.factory.makeLiveFS(registrant=self.person, owner=self.person, distroseries=distroseries, name="two") browser = self.getViewBrowser(livefs, user=self.person) browser.getLink("Edit live filesystem").click() browser.getControl("Name").value = "two" browser.getControl("Update live filesystem").click() self.assertEqual( "There is already a live filesystem for Grumpy owned by " "Test Person with this name.", extract_text(find_tags_by_class(browser.contents, "message")[1]))
def test_rescore_build_invalid_score(self): """Build scores can only take numbers.""" queue = self.factory.makeSourcePackageRecipeBuildJob() build = queue.specific_job.build transaction.commit() build_url = canonical_url(build) logout() browser = self.getUserBrowser(build_url, user=self.admin) browser.getLink('Rescore build').click() self.assertEqual( browser.getLink('Cancel').url, build_url) browser.getControl('Score').value = 'tentwentyfour' browser.getControl('Rescore build').click() self.assertEqual( extract_text(find_tags_by_class(browser.contents, 'message')[1]), 'Invalid integer data')
def _getInformationalMessage(self, contents): message = find_tags_by_class(contents, 'informational message') return extract_text(message[0])
def _getSubscribers(self, contents): subscriptions = find_tags_by_class(contents, 'repository-subscribers')[0] for subscriber in subscriptions.findAll('div'): yield extract_text(subscriber.renderContents())