def test_contact_is_possible(self): # The contact_is_possible property checks has_valid_email_address # and contact_is_allowed. team = self.factory.makeTeam() sender = self.factory.makePerson() with person_logged_in(sender): view = create_initialized_view(team, '+contactuser') self.assertTrue(view.has_valid_email_address) self.assertTrue(view.contact_is_allowed) self.assertTrue(view.contact_is_possible) other_sender = self.makeThrottledSender() with person_logged_in(other_sender): view = create_initialized_view(team, '+contactuser') self.assertTrue(view.has_valid_email_address) self.assertFalse(view.contact_is_allowed) self.assertFalse(view.contact_is_possible) with person_logged_in(team.teamowner): team.teamowner.leave(team) with person_logged_in(sender): view = create_initialized_view(team, '+contactuser') self.assertTrue(view.contact_is_allowed) self.assertFalse(view.has_valid_email_address) self.assertFalse(view.contact_is_possible)
def test_existing_team_error(self): """ Do not allow a new team with the same name as an existing team. The ObjectReassignmentView displays radio buttons that give you the option to create a team as opposed to using an existing team. If the user tries to create a new team with the same name as an existing team, an error is displayed. """ a_team, b_team, c_team, owner = self._makeTeams() view = create_initialized_view( c_team, '+reassign', principal=owner) self.assertEqual( ['field.owner', 'field.existing'], list(w.name for w in view.widgets)) form = { 'field.owner': 'a-team', 'field.existing': 'new', 'field.actions.change': 'Change', } view = create_initialized_view( a_team, '+reassign', form=form, principal=owner) self.assertEqual( [html_escape( u"There's already a person/team with the name 'a-team' in " "Launchpad. Please choose a different name or select the " "option to make that person/team the new owner, if that's " "what you want.")], view.errors)
def test_delete_action_public_bug(self): # Bug attachments can be removed from a bug. user = self.factory.makePerson() login_person(user) create_initialized_view( self.bugattachment, name='+edit', form=self.DELETE_FORM_DATA) self.assertEqual(0, self.bug.attachments.count())
def test_getAcknowledgementMessage_product_in_project_group(self): # If a product is part of a project group and if the project # group has a customized bug filing confirmation message, # this message is displayed. project_group = self.factory.makeProject() product = self.factory.makeProduct(project=project_group) # Without any customized bug filing confirmation message, the # default message is used. view = create_initialized_view(product, name='+filebug') self.assertEqual( u"Thank you for your bug report.", view.getAcknowledgementMessage(product)) # If the project group has a customized message, it is used. project_group.bug_reported_acknowledgement = ( "Thanks for filing a bug for one of our many products.") view = create_initialized_view(product, name='+filebug') self.assertEqual( u"Thanks for filing a bug for one of our many products.", view.getAcknowledgementMessage(product)) # But if the product itself has a customized message too, this # message is used instead of the project group's message. product.bug_reported_acknowledgement = ( u"Thanks for filing a bug for this very special product.") view = create_initialized_view(product, name='+filebug') self.assertEqual( u"Thanks for filing a bug for this very special product.", view.getAcknowledgementMessage(product))
def test_filter_uses_bug_notification_level(self): # A user can specify a bug_notification_level on the +filter form. displayed_levels = [ level for level in BugNotificationLevel.items] for level in displayed_levels: person = self.factory.makePerson() with person_logged_in(person): subscription = self.target.addBugSubscription( person, person) initial_filter = subscription.bug_filters.one() form = { "field.description": "New description", "field.statuses": ["NEW", "INCOMPLETE"], "field.importances": ["LOW", "MEDIUM"], "field.tags": u"foo bar", "field.find_all_tags": "on", 'field.bug_notification_level': level.title, "field.actions.create": "Create", } create_initialized_view( subscription, name="+new-filter", form=form) filters = subscription.bug_filters new_filter = [filter for filter in filters if filter != initial_filter][0] self.assertEqual(filters.count(), 2) self.assertEqual( level, new_filter.bug_notification_level, "Bug notification level of filter should be %s, " "is actually %s." % ( level.name, new_filter.bug_notification_level.name))
def test_getAcknowledgementMessage_product(self): # If there is not customized confirmation message, a default # message is displayed. product = self.factory.makeProduct() view = create_initialized_view(product, name='+filebug') self.assertEqual( u"Thank you for your bug report.", view.getAcknowledgementMessage(product)) # If a product contains a customized bug filing confirmation # message, it is retrieved by # FilebugViewBase.bug_reported_acknowledgement product.bug_reported_acknowledgement = ( u"We really appreciate your bug report") view = create_initialized_view(product, name='+filebug') self.assertEqual( u"We really appreciate your bug report", view.getAcknowledgementMessage(product)) # If the custom message is set to a string containing only white, # space, the default message is used again. product.bug_reported_acknowledgement = ' \t' view = create_initialized_view(product, name='+filebug') self.assertEqual( u"Thank you for your bug report.", view.getAcknowledgementMessage(product))
def test_bug_filed_acknowlegdgement_notification(self): # When a user files a bug, an acknowledgement notification is added # to the response. product = self.factory.makeProduct() login_person(product.owner) create_initialized_view(product, name='+filebug') form_data = { 'title': 'A bug title', 'comment': 'whatever', } view = create_initialized_view(product, name='+filebug') view.submit_bug_action.success(form_data) self.assertEqual( ['<p class="last">Thank you for your bug report.</p>'], [notification.message for notification in view.request.response.notifications]) # This message can be customized. product.bug_reported_acknowledgement = ( u"We really appreciate your bug report") view = create_initialized_view(product, name='+filebug') view.submit_bug_action.success(form_data) self.assertEqual( [u'<p class="last">We really appreciate your bug report</p>'], [notification.message for notification in view.request.response.notifications])
def test_build_records_view(self): # The BuildRecordsView can also be used to filter by architecture tag. distroseries = self.factory.makeDistroSeries() arch_list = [] for i in range(5): das = self.factory.makeDistroArchSeries(distroseries=distroseries) arch_list.append(das.architecturetag) build = self.factory.makeBinaryPackageBuild( distroarchseries=das, archive=distroseries.main_archive, status=BuildStatus.NEEDSBUILD) build.updateStatus(BuildStatus.BUILDING) build.updateStatus(BuildStatus.FULLYBUILT) view = create_initialized_view( distroseries, name="+builds", form={'build_state': 'all'}) view.setupBuildList() build_arches = [build.arch_tag for build in view.complete_builds] self.assertEquals(arch_list.sort(), build_arches.sort()) view = create_initialized_view( distroseries, name="+builds", form={ 'build_state': 'all', 'arch_tag': arch_list[0]}) view.setupBuildList() self.assertEquals(len(view.complete_builds), 1) self.assertEquals(view.complete_builds[0].arch_tag, arch_list[0]) # There is an extra entry for 'All architectures' self.assertEquals(len(view.architecture_options), len(arch_list) + 1) selected = [] option_arches = [] for option in view.architecture_options: option_arches.append(option['name']) if option['selected'] is not None: selected.append(option['name']) self.assertEquals(option_arches.sort(), arch_list.sort()) self.assertTrue(len(selected), 1) self.assertEquals(selected, [arch_list[0]])
def test_unmute_and_subscribe(self): # Using the "unmute bug mail from this bug and subscribe me to this # bug" option when the user has muted their email will unmute and # subscribe. with person_logged_in(self.person): self.bug.mute(self.person, self.person) level = BugNotificationLevel.METADATA form_data = { 'field.subscription': 'update-subscription', 'field.bug_notification_level': level.title, # Although this isn't used we must pass it for the # sake of form validation. 'field.actions.continue': 'Continue', } create_initialized_view( self.bug.default_bugtask, form=form_data, name='+subscribe') self.assertFalse(self.bug.isMuted(self.person)) subscription = self.bug.getSubscriptionForPerson(self.person) self.assertEqual( BugNotificationLevel.METADATA, subscription.bug_notification_level, "Bug notification level of subscription should be METADATA, is " "actually %s." % (subscription.bug_notification_level.title if subscription is not None else '[not subscribed!]'))
def test_mute_subscription_link_shown_for_team_subscription(self): # If the person belongs to a team with a structural subscription, # then the mute link will be displayed to them. person = self.factory.makePerson(name="a-person") team_owner = self.factory.makePerson(name="team-owner") team = self.factory.makeTeam(owner=team_owner, name="subscribed-team") with person_logged_in(team_owner): team.addMember(person, team_owner) self.target.addBugSubscription(team, team_owner) with person_logged_in(person): self.assertFalse(self.bug.isMuted(person)) self.assertTrue( self.bug.personIsAlsoNotifiedSubscriber( person), "Person should be a notified subscriber") view = create_initialized_view( self.bug, name="+portlet-subscription") self.assertTrue(view.user_should_see_mute_link, "User should see mute link.") contents = view.render() self.assertTrue('mute_subscription' in contents, "'mute_subscription' not in contents.") self.assertFalse( self._hasCSSClass( contents, 'mute-link-container', 'hidden')) create_initialized_view( self.bug.default_bugtask, name="+mute", form={'field.actions.mute': 'Mute bug mail'}) self.assertTrue(self.bug.isMuted(person))
def test_bug_mute_self_view_mutes_bug(self): # The BugMuteSelfView mutes bug mail for the current user when # its form is submitted. with person_logged_in(self.person): self.assertFalse(self.bug.isMuted(self.person)) create_initialized_view( self.bug.default_bugtask, name="+mute", form={'field.actions.mute': 'Mute bug mail'}) self.assertTrue(self.bug.isMuted(self.person))
def test_add_distro_enabled_restricted_processors(self): creation_form = self.getDefaultAddDict() creation_form['field.enabled_restricted_processors'] = [] create_initialized_view( self.distributionset, '+add', principal=self.admin, method='POST', form=creation_form) distribution = self.distributionset.getByName('newbuntu') self.assertContentEqual( [], distribution.main_archive.enabled_restricted_processors)
def test_package_derivatives_email(self): # Test that the edit form allows changing package_derivatives_email edit_form = self.getDefaultEditDict() email = '{package_name}[email protected]' edit_form['field.package_derivatives_email'] = email create_initialized_view( self.distribution, '+edit', principal=self.distribution.owner, method="POST", form=edit_form) self.assertEqual(self.distribution.package_derivatives_email, email)
def test_registrant_set_by_creation(self): # The registrant field should be set to the Person creating # the distribution. creation_form = self.getDefaultAddDict() create_initialized_view( self.distributionset, '+add', principal=self.admin, method='POST', form=creation_form) distribution = self.distributionset.getByName('newbuntu') self.assertEqual(distribution.owner, self.admin) self.assertEqual(distribution.registrant, self.admin)
def test_remove_duplicate(self): with person_logged_in(self.bug_owner): self.bug.markAsDuplicate(self.duplicate_bug) form = { 'field.actions.remove': u'Remove Duplicate', } create_initialized_view( self.bug.default_bugtask, name="+duplicate", principal=self.bug_owner, form=form) self.assertIsNone(self.bug.duplicateof)
def test_delete_action_private_bug(self): # Subscribers of a private bug can delete attachments. user = self.factory.makePerson() self.bug.setPrivate(True, self.bug_owner) with person_logged_in(self.bug_owner): self.bug.subscribe(user, self.bug_owner) login_person(user) create_initialized_view( self.bugattachment, name='+edit', form=self.DELETE_FORM_DATA) self.assertEqual(0, self.bug.attachments.count())
def test_create_duplicate(self): with person_logged_in(self.bug_owner): form = { 'field.actions.change': u'Set Duplicate', 'field.duplicateof': u'%s' % self.duplicate_bug.id } create_initialized_view( self.bug.default_bugtask, name="+duplicate", principal=self.bug_owner, form=form) self.assertEqual(self.duplicate_bug, self.bug.duplicateof)
def test_eta(self): # BuildView.eta returns a non-None value when it should, or None # when there's no start time. build = self.factory.makeBinaryPackageBuild() build.queueBuild() self.factory.makeBuilder(processor=build.processor, virtualized=True) self.assertIsNot(None, create_initialized_view(build, '+index').eta) with admin_logged_in(): build.archive.disable() flush_database_caches() self.assertIs(None, create_initialized_view(build, '+index').eta)
def test_change_require_virtualized(self): edit_form = self.getDefaultEditDict() edit_form['field.require_virtualized'] = 'on' self.distribution.main_archive.require_virtualized = False create_initialized_view( self.distribution, '+edit', principal=self.admin, method='POST', form=edit_form) self.assertEqual( True, self.distribution.main_archive.require_virtualized)
def test_add_distro_require_virtualized(self): creation_form = self.getDefaultAddDict() creation_form['field.require_virtualized'] = '' create_initialized_view( self.distributionset, '+add', principal=self.admin, method='POST', form=creation_form) distribution = self.distributionset.getByName('newbuntu') self.assertEqual( False, distribution.main_archive.require_virtualized)
def test_change_action_public_bug(self): # Properties of attachments for public bugs can be # changed by every user. user = self.factory.makePerson() login_person(user) create_initialized_view( self.bugattachment, name='+edit', form=self.CHANGE_FORM_DATA) self.assertEqual('new description', self.bugattachment.title) self.assertTrue(self.bugattachment.is_patch) self.assertEqual( 'application/whatever', self.bugattachment.libraryfile.mimetype)
def test_view_query_count(self): # Test that the view bulk loads artifacts. person = self.factory.makePerson() for x in range(0, 15): self.makeArtifactGrantee(person, True, True, False) pillarperson = PillarPerson(self.pillar, person) # Invalidate the Storm cache and check the query count. IStore(self.pillar).invalidate() with StormStatementRecorder() as recorder: create_initialized_view(pillarperson, '+index') self.assertThat(recorder, HasQueryCount(LessThan(13)))
def test_change_enabled_restricted_processors(self): edit_form = self.getDefaultEditDict() edit_form['field.enabled_restricted_processors'] = [] self.distribution.main_archive.enabled_restricted_processors = ( self.restricted_processors) create_initialized_view( self.distribution, '+edit', principal=self.admin, method='POST', form=edit_form) self.assertContentEqual( [], self.distribution.main_archive.enabled_restricted_processors)
def test_contact_is_allowed(self): # The contact_is_allowed property checks if the user has not exceeded # the quota.. team = self.factory.makeTeam() sender = self.factory.makePerson() with person_logged_in(sender): view = create_initialized_view(team, '+contactuser') self.assertTrue(view.contact_is_allowed) other_sender = self.makeThrottledSender() with person_logged_in(other_sender): view = create_initialized_view(team, '+contactuser') self.assertFalse(view.contact_is_allowed)
def _test_ajax_batch_navigation_feature_flag(self, context, user=None): # The Javascript to wire up the ajax batch navigation behavior is # correctly hidden behind a feature flag. flags = {u"ajax.batch_navigator.enabled": u"true"} with FeatureFixture(flags): view = create_initialized_view( context, name="+branches", rootsite='code', principal=user) self.assertTrue( 'Y.lp.app.batchnavigator.BatchNavigatorHooks' in view()) view = create_initialized_view( context, name="+branches", rootsite='code', principal=user) self.assertFalse( 'Y.lp.app.batchnavigator.BatchNavigatorHooks' in view())
def test_has_valid_email_address(self): # The has_valid_email_address property checks the len of the # recipient set. team = self.factory.makeTeam() sender = self.factory.makePerson() with person_logged_in(sender): view = create_initialized_view(team, '+contactuser') self.assertTrue(view.has_valid_email_address) with person_logged_in(team.teamowner): team.teamowner.leave(team) with person_logged_in(sender): view = create_initialized_view(team, '+contactuser') self.assertFalse(view.has_valid_email_address)
def test_search_macro_title(self): # The title text is displayed for the macro `simple-search-form`. product = self.factory.makeProduct( displayname='Test Product', official_malone=True) view = create_initialized_view(product, '+bugs') self.assertEqual( 'Search bugs in Test Product', view.search_macro_title) # The title is shown. form_title_matches = Tag( 'Search form title', 'h3', text=view.search_macro_title) view = create_initialized_view(product, '+bugs') self.assertThat(view.render(), HTMLContains(form_title_matches))
def test_change_action_private_bug(self): # Subscribers of a private bug can edit attachments. user = self.factory.makePerson() self.bug.setPrivate(True, self.bug_owner) with person_logged_in(self.bug_owner): self.bug.subscribe(user, self.bug_owner) transaction.commit() login_person(user) create_initialized_view( self.bugattachment, name='+edit', form=self.CHANGE_FORM_DATA) self.assertEqual('new description', self.bugattachment.title) self.assertTrue(self.bugattachment.is_patch) self.assertEqual( 'application/whatever', self.bugattachment.libraryfile.mimetype)
def test_proprietary_branch_for_series_user_has_artifact_grant(self): # A user can be the owner of a branch which is the series # branch of a proprietary product, and the user may only have # an access grant for the branch but no policy grant for the # product. In this case, the branch owner does get any information #about the series. product_owner = self.factory.makePerson() product = self.factory.makeProduct( owner=product_owner, information_type=InformationType.PROPRIETARY) branch_owner = self.factory.makePerson() sharing_service = getUtility(IService, 'sharing') with person_logged_in(product_owner): # The branch owner needs to have a policy grant at first # so that they can create the branch. sharing_service.sharePillarInformation( product, branch_owner, product_owner, {InformationType.PROPRIETARY: SharingPermission.ALL}) proprietary_branch = self.factory.makeProductBranch( product, owner=branch_owner, name='special-branch', information_type=InformationType.PROPRIETARY) series = self.factory.makeProductSeries( product=product, branch=proprietary_branch) sharing_service.deletePillarGrantee( product, branch_owner, product_owner) # Admin help is needed: Product owners do not have the # permission to create artifact grants for branches they # do not own, and the branch owner does have the permission # to issue grants related to the product. with admin_logged_in(): sharing_service.ensureAccessGrants( [branch_owner], product_owner, branches=[proprietary_branch]) with person_logged_in(branch_owner): view = create_initialized_view( branch_owner, name="+branches", rootsite='code', principal=branch_owner) self.assertIn(proprietary_branch, view.branches().batch) # The product series related to the branch is not returned # for the branch owner. self.assertEqual( [], view.branches().getProductSeries(proprietary_branch)) with person_logged_in(product_owner): # The product series related to the branch is returned # for the product owner. view = create_initialized_view( branch_owner, name="+branches", rootsite='code', principal=branch_owner) self.assertEqual( [series], view.branches().getProductSeries(proprietary_branch))
def test_reassign_distro_change_owner_not_registrant(self): # Reassigning a distribution should not change the registrant. admin = login_celebrity('admin') distribution = self.factory.makeDistribution( name="boobuntu", owner=self.owner, registrant=self.registrant) reassign_form = { 'field.owner': self.simple_user.name, 'field.existing': 'existing', 'field.actions.change': 'Change', } create_initialized_view( distribution, '+reassign', principal=admin, method='POST', form=reassign_form) self.assertEqual(distribution.owner, self.simple_user) self.assertEqual(distribution.registrant, self.registrant)
def test_enable_blacklist_options_for_archive_admin(self): # To see the blacklist options enabled the user needs to be an # archive admin. ds_diff = self.factory.makeDistroSeriesDifference() archive_admin = self.factory.makeArchiveAdmin( archive=ds_diff.derived_series.main_archive) request = LaunchpadTestRequest(HTTP_X_REQUESTED_WITH='XMLHttpRequest') with person_logged_in(archive_admin): view = create_initialized_view( ds_diff, '+listing-distroseries-extra', request=request) self.assertTrue(view.enable_blacklist_options)
def test_owner_view_attributes(self): view = create_initialized_view( self.product, name='+configure-bugtracker') label = 'Configure bug tracker' self.assertEqual(label, view.label) fields = [ 'bugtracker', 'enable_bug_expiration', 'remote_product', 'bug_reporting_guidelines', 'bug_reported_acknowledgement', 'enable_bugfiling_duplicate_search', 'bug_supervisor'] self.assertEqual(fields, view.field_names) self.assertEqual('http://launchpad.dev/boing', view.next_url) self.assertEqual('http://launchpad.dev/boing', view.cancel_url)
def test_bug_mute_for_individual_structural_subscription(self): # If the person has a structural subscription to the pillar, # then the mute link will be displayed to them. person = self.factory.makePerson(name="a-person") with person_logged_in(person): self.target.addBugSubscription(person, person) self.assertFalse(self.bug.isMuted(person)) view = create_initialized_view(self.bug, name="+portlet-subscription") self.assertTrue(view.user_should_see_mute_link, "User should see mute link.") contents = view.render() self.assertTrue('mute_subscription' in contents, "'mute_subscription' not in contents.") self.assertFalse( self._hasCSSClass(contents, 'mute-link-container', 'hidden')) create_initialized_view( self.bug.default_bugtask, name="+mute", form={'field.actions.mute': 'Mute bug mail'}) self.assertTrue(self.bug.isMuted(person))
def test_private_superteams_anonymous(self): # If the viewer is anonymous, the portlet is not shown. team = self.createTeams() self.factory.makePerson() view = create_initialized_view(team, '+index', server_url=canonical_url(team), path_info='') html = view() superteams = find_tag_by_id(html, 'subteam-of') self.assertIs(None, superteams) self.assertEqual([], view.super_teams)
def test_subscriber_ids(self): spec = self.factory.makeSpecification() subscriber = self.factory.makePerson() person = self.factory.makePerson() with person_logged_in(person): spec.subscribe(subscriber, subscriber) view = create_initialized_view( spec, name="+blueprint-portlet-subscribers-ids") subscriber_ids = dict( (subscriber.name, 'subscriber-%s' % subscriber.id) for subscriber in [person, subscriber]) self.assertEqual(subscriber_ids, view.subscriber_ids)
def test_unlinking(self): component = self._makeComponent(u'Example') dsp = self._makeUbuntuSourcePackage('example') component.distro_source_package = dsp form = self._makeForm(None) view = create_initialized_view(component, name='+edit', form=form) self.assertEqual([], view.errors) notifications = view.request.response.notifications self.assertEqual(None, component.distro_source_package) expected = "alpha:Example is now unlinked." self.assertEqual(expected, notifications.pop().message)
def test_cannot_rename_team_with_active_mailinglist(self): # Because renaming mailing lists is non-trivial in Mailman 2.1, # renaming teams with mailing lists is prohibited. owner = self.factory.makePerson() team = self.factory.makeTeam(owner=owner) self.factory.makeMailingList(team, owner) with person_logged_in(owner): view = create_initialized_view(team, name=self.view_name) self.assertTrue(view.form_fields['name'].for_display) self.assertEqual( 'This team has a mailing list and may not be renamed.', view.widgets['name'].hint)
def test_ask_question_uses_launchpad(self): bug_target = self._makeBugTargetProduct(bug_tracker='launchpad', packaging=True) login_person(bug_target.owner) bug_target.official_answers = True view = create_initialized_view(bug_target, '+bugs', principal=bug_target.owner) url = canonical_url(bug_target, rootsite='answers', view_name='+addquestion') self.assertEqual(url, view.addquestion_url)
def test_filebug_information_type_vocabulary(self): # The vocabulary for information_type when filing a bug is created # correctly. product = self.factory.makeProduct(official_malone=True) with person_logged_in(product.owner): view = create_initialized_view(product, '+filebug', principal=product.owner) html = view.render() soup = BeautifulSoup(html) for info_type in product.getAllowedBugInformationTypes(): self.assertIsNotNone(soup.find('label', text=info_type.title))
def test_view_filters_security_wisely(self): # There are bugs in the sharingdetails view that not everyone with # `launchpad.Driver` -- the permission level for the page -- should be # able to see. pillarperson = self.getPillarPerson(security=True) logout() login_person(self.driver) view = create_initialized_view(pillarperson, '+index') # The page loads self.assertEqual(pillarperson.person.displayname, view.page_title) # The bug, which is not shared with the driver, is not included. self.assertEqual(0, view.shared_bugs_count)
def test_search_batch_request(self): # A search request with a 'batch_request' query parameter causes the # view to just render the next batch of results. product = self.factory.makeProduct() form = {'search': 'Search'} view = create_initialized_view(product, '+bugs', form=form, query_string='batch_request=True') content = view() self.assertIsNone(find_main_content(content)) self.assertIsNotNone(find_tag_by_id(content, 'bugs-batch-links-upper'))
def test_view_range_factory(self): # Test the view range factory is properly configured. view = create_initialized_view(self.pillar, name='+sharing') range_factory = view.grantees().batch.range_factory def test_range_factory(): row = range_factory.resultset.get_plain_result_set()[0] range_factory.getOrderValuesFor(row) self.assertThat( test_range_factory, Not(Raises(MatchesException(StormRangeFactoryError))))
def test_announcement_info_with_publication_date(self): product = self.factory.makeProduct(displayname=u"Foo") announcer = self.factory.makePerson(displayname=u"Bar Baz") announced = datetime(2007, 1, 12, tzinfo=utc) announcement = product.announce( announcer, "Hello World", publication_date=announced) view = create_initialized_view(announcement, "+index") root = html.fromstring(view()) [reg_para] = root.cssselect("p.registered") self.assertEqual( "Written for Foo by Bar Baz on 2007-01-12", normalize_whitespace(reg_para.text_content()))
def test_submit_action_unauthorised(self): # An unauthorised user sees an error on the bug target page. login_person(None) view = create_initialized_view(self.bug_task, name='+nominate') self.assertEqual(canonical_url(self.bug_task), view.request.response.getHeader('Location')) notifications = view.request.notifications self.assertEqual(1, len(notifications)) self.assertEqual(BrowserNotificationLevel.ERROR, notifications[0].level) self.assertEqual("You do not have permission to nominate this bug.", notifications[0].message)
def test_both_request_diff_texts_rendered(self): # An unlinked description of a potential diff is displayed when # no diff is present. ds_diff = self.factory.makeDistroSeriesDifference( set_base_version=True) with person_logged_in(self.factory.makePerson()): view = create_initialized_view( ds_diff, '+listing-distroseries-extra')#, principal=user) soup = BeautifulSoup(view()) # Both diffs present simple text repr. of proposed diff. self.assertEqual(2, self.number_of_request_diff_texts(soup))
def test_owner_appoint_self_from_none(self): # This also verifies that displaynames are escaped. form = self._makeForm(self.owner) view = create_initialized_view(self.product, name='+bugsupervisor', form=form) self.assertEqual([], view.errors) self.assertEqual(self.product.bug_supervisor, self.owner) notifications = view.request.response.notifications self.assertEqual(1, len(notifications)) expected = 'Bug supervisor privilege granted.' self.assertEqual(expected, notifications.pop().message)
def verify_admincomment_required(self, action_name, view_name): # Empty comments are not permitted for any state change. form = { 'field.admincomment': '', 'field.actions.change': action_name, } view = create_initialized_view(self.signed_coc, name=view_name, form=form, principal=self.admin) self.assertEqual(1, len(view.errors)) self.assertEqual('admincomment', view.errors[0].field_name)
def test_add_member_success(self): member = self.factory.makePerson(name="a-member") form = self.getForm(member) view = create_initialized_view(self.team, "+addmember", form=form) self.assertEqual([], view.errors) notifications = view.request.response.notifications self.assertEqual(1, len(notifications)) self.assertEqual( 'A-member (a-member) has been added as a member of this team.', notifications[0].message) self.assertTrue(member.inTeam(self.team)) self.assertEqual(None, view.widgets['newmember']._getCurrentValue())
def test_view_attributes(self): component = self._makeComponent(u'Example') dsp = self._makeUbuntuSourcePackage('example') form = self._makeForm(dsp) view = create_initialized_view(component, name='+edit', form=form) label = 'Link a distribution source package to Example component' self.assertEqual(label, view.label) self.assertEqual('Link component', view.page_title) self.assertEqual(['sourcepackagename'], view.field_names) url = canonical_url(component.component_group.bug_tracker) self.assertEqual(url, view.next_url) self.assertEqual(url, view.cancel_url)
def test_offsite_url(self): """The specification URL is rendered when present.""" spec = self.factory.makeSpecification() login_person(spec.owner) spec.specurl = 'http://eg.dom/parrot' view = create_initialized_view(spec, name='+index', principal=spec.owner, rootsite='blueprints') li = find_tag_by_id(view.render(), 'spec-url') self.assertEqual('nofollow', li.a['rel']) self.assertEqual(spec.specurl, li.a['href'])
def test_person_with_cs_can_create_private_team(self): personset = getUtility(IPersonSet) team = self.factory.makeTeam( membership_policy=TeamMembershipPolicy.MODERATED) self.factory.grantCommercialSubscription(team) team_name = self.factory.getUniqueString() form = { 'field.name': team_name, 'field.displayname': 'New Team', 'field.membership_policy': 'RESTRICTED', 'field.visibility': 'PRIVATE', 'field.actions.create': 'Create', } with person_logged_in(team.teamowner): create_initialized_view(personset, name=self.view_name, principal=team.teamowner, form=form) team = personset.getByName(team_name) self.assertIsNotNone(team) self.assertEqual(PersonVisibility.PRIVATE, team.visibility)
def test_unchanged_lifecycle_has_no_notification(self): spec = self.factory.makeSpecification( implementation_status=SpecificationImplementationStatus.STARTED) login_person(spec.owner) form = { 'field.implementation_status': 'SLOW', 'field.actions.change': 'Change', } view = create_initialized_view(spec, name='+status', form=form) self.assertEqual(SpecificationImplementationStatus.SLOW, spec.implementation_status) self.assertEqual(0, len(view.request.notifications))
def test_upstream_project(self): # BugTaskSearchListingView.upstream_project and # BugTaskSearchListingView.upstream_launchpad_project are # None for all bug targets except SourcePackages # and DistributionSourcePackages. bug_target = self._makeBugTargetProduct(bug_tracker='launchpad', packaging=True) view = create_initialized_view(bug_target, '+bugs', principal=bug_target.owner) self.assertIs(None, view.upstream_project) self.assertIs(None, view.upstream_launchpad_project)
def test_new_series_help(self): # The LP branch URL displayed to the user on the +code-summary page # for a product series will relate to that series instead of to the # default series for the Product. product = self.factory.makeProduct() series = self.factory.makeProductSeries(product=product) person = product.owner branch_url = "lp:~%s/%s/%s" % (person.name, product.name, series.name) with person_logged_in(person): self.factory.makeSSHKey(person=person) view = create_initialized_view(series, '+code-summary') self.assertThat(view(), Contains(branch_url))
def test_refuses_proprietary_products(self): owner = self.factory.makePerson() product = self.factory.makeProduct( owner=owner, information_type=InformationType.PROPRIETARY) with person_logged_in(owner): release = self.factory.makeProductRelease(product=product) form = self.makeForm('something.tar.gz') view = create_initialized_view(release, '+adddownloadfile', form=form) self.assertEqual(['Only public projects can have download files.'], view.errors)
def test_contact_admins(self): sender = self.factory.makePerson() team = self.factory.makeTeam() with person_logged_in(sender): view = create_initialized_view(team, '+index') self.assertIs(ContactViaWebNotificationRecipientSet.TO_ADMINS, view.group_to_contact) self.assertEqual("Contact this team's admins", view.specific_contact_text) self.assertEqual( "Send an email to this team's admins through Launchpad", view.contact_link_title)
def test_contact_members(self): team = self.factory.makeTeam() admin = team.teamowner with person_logged_in(admin): view = create_initialized_view(team, '+index') self.assertIs(ContactViaWebNotificationRecipientSet.TO_MEMBERS, view.group_to_contact) self.assertEqual("Contact this team's members", view.specific_contact_text) self.assertEqual( "Send an email to your team's members through Launchpad", view.contact_link_title)
def test_person_with_expired_cs_does_not_see_visibility(self): personset = getUtility(IPersonSet) team = self.factory.makeTeam( membership_policy=TeamMembershipPolicy.MODERATED) product = self.factory.makeProduct(owner=team) self.factory.makeCommercialSubscription(product, expired=True) with person_logged_in(team.teamowner): view = create_initialized_view(personset, name=self.view_name, principal=team.teamowner) self.assertNotIn('visibility', [field.__name__ for field in view.form_fields])
def test_batching(self): team = self.makeTeamWithMailingList() sender, message, held_message = self.makeHeldMessage(team) for i in range(5): self.makeHeldMessage(team, sender) view = create_initialized_view( team, name='+mailinglist-moderate', principal=team.teamowner) self.assertEqual(6, view.hold_count) self.assertEqual('messages', view.held_messages.heading) self.assertTextMatchesExpressionIgnoreWhitespace( '.*upper-batch-nav-batchnav-next.*lower-batch-nav-batchnav-next.*', view.render())
def test_information_type_proprietary(self): # A ProductSeries view should get its information_type # from the related product even if the product is changed to # PROPRIETARY. owner = self.factory.makePerson() information_type = InformationType.PROPRIETARY product = self.factory.makeProduct(owner=owner, information_type=information_type) series = self.factory.makeProductSeries(product=product) with person_logged_in(owner): view = create_initialized_view(series, '+index') self.assertEqual('Proprietary', view.information_type)