Exemplo n.º 1
0
    def test_data_team_subscription_member_looks(self):
        # For a team subscription, subscriber_data_js has can_edit
        # set to true for team member.
        bug = self._makeBugWithNoSubscribers()
        member = self.factory.makePerson()
        teamowner = self.factory.makePerson(name="team-owner",
                                            displayname="Team Owner")
        subscriber = self.factory.makeTeam(name='team',
                                           displayname='Team Name',
                                           owner=teamowner,
                                           members=[member])
        with person_logged_in(subscriber.teamowner):
            bug.subscribe(subscriber,
                          subscriber.teamowner,
                          level=BugNotificationLevel.LIFECYCLE)
        harness = LaunchpadFormHarness(bug, BugPortletSubscribersWithDetails)
        api_request = IWebServiceClientRequest(harness.request)

        expected_result = {
            'subscriber': {
                'name': 'team',
                'display_name': 'Team Name',
                'is_team': True,
                'can_edit': True,
                'web_link': canonical_url(subscriber),
                'self_link': absoluteURL(subscriber, api_request),
                'display_subscribed_by': \
                    'Subscribed by Team Owner (team-owner)',
                },
            'subscription_level': "Lifecycle",
            }
        with person_logged_in(subscriber.teamowner):
            self.assertEqual(dumps([expected_result]),
                             harness.view.subscriber_data_js)
Exemplo n.º 2
0
    def test_data_subscription_lp_admin(self):
        # For a subscription, subscriber_data_js has can_edit
        # set to true for a Launchpad admin.
        question = self._makeQuestionWithNoSubscribers()
        member = self.factory.makePerson()
        subscriber = self.factory.makePerson(name='user',
                                             displayname='Subscriber Name')
        with person_logged_in(member):
            question.subscribe(subscriber, subscriber)
        view = create_view(question, '+portlet-subscribers-details')
        api_request = IWebServiceClientRequest(view.request)

        expected_result = {
            'subscriber': {
                'name': 'user',
                'display_name': 'Subscriber Name',
                'is_team': False,
                'can_edit': True,
                'web_link': canonical_url(subscriber),
                'self_link': absoluteURL(subscriber, api_request)
            },
            'subscription_level': "Direct",
        }

        # Login as admin
        admin = getUtility(IPersonSet).find(ADMIN_EMAIL).any()
        with person_logged_in(admin):
            self.assertEqual(dumps([expected_result]), view.subscriber_data_js)
Exemplo n.º 3
0
    def test_data_person_subscription(self):
        # subscriber_data_js returns JSON string of a list
        # containing all subscriber information needed for
        # subscribers_list.js subscribers loading.
        bug = self._makeBugWithNoSubscribers()
        subscriber = self.factory.makePerson(name='user',
                                             displayname='Subscriber Name')
        with person_logged_in(subscriber):
            bug.subscribe(subscriber,
                          subscriber,
                          level=BugNotificationLevel.LIFECYCLE)
        harness = LaunchpadFormHarness(bug, BugPortletSubscribersWithDetails)
        api_request = IWebServiceClientRequest(harness.request)

        expected_result = {
            'subscriber': {
                'name': 'user',
                'display_name': 'Subscriber Name',
                'is_team': False,
                'can_edit': False,
                'web_link': canonical_url(subscriber),
                'self_link': absoluteURL(subscriber, api_request),
                'display_subscribed_by': 'Self-subscribed',
            },
            'subscription_level': "Lifecycle",
        }
        self.assertEqual(dumps([expected_result]),
                         harness.view.subscriber_data_js)
Exemplo n.º 4
0
    def test_data_team_subscription(self):
        # For a team subscription, subscriber_data_js has is_team set
        # to true.
        question = self._makeQuestionWithNoSubscribers()
        teamowner = self.factory.makePerson(name="team-owner",
                                            displayname="Team Owner")
        subscriber = self.factory.makeTeam(name='team',
                                           displayname='Team Name',
                                           owner=teamowner)
        with person_logged_in(subscriber.teamowner):
            question.subscribe(subscriber, subscriber.teamowner)
        view = create_view(question, '+portlet-subscribers-details')
        api_request = IWebServiceClientRequest(view.request)

        expected_result = {
            'subscriber': {
                'name': 'team',
                'display_name': 'Team Name',
                'is_team': True,
                'can_edit': False,
                'web_link': canonical_url(subscriber),
                'self_link': absoluteURL(subscriber, api_request)
            },
            'subscription_level': "Direct",
        }
        self.assertEqual(dumps([expected_result]), view.subscriber_data_js)
Exemplo n.º 5
0
    def test_data_team_subscription_member_looks(self):
        # For a team subscription, answercontact_data_js has can_edit
        # set to true for team member.
        question = self.factory.makeQuestion()
        member = self.factory.makePerson()
        teamowner = self.factory.makePerson(
            name="team-owner", displayname="Team Owner")
        contact = self.factory.makeTeam(
            name='team', displayname='Team Name', owner=teamowner,
            members=[member])
        contact.addLanguage(getUtility(ILanguageSet)['en'])
        with person_logged_in(contact.teamowner):
            question.target.addAnswerContact(contact, contact.teamowner)
        view = create_view(question.target, '+portlet-answercontacts-details')
        api_request = IWebServiceClientRequest(view.request)

        expected_result = {
            'subscriber': {
                'name': 'team',
                'display_name': 'Team Name',
                'is_team': True,
                'can_edit': True,
                'web_link': canonical_url(contact),
                'self_link': absoluteURL(contact, api_request)
                }
            }
        with person_logged_in(contact.teamowner):
            self.assertEqual(
                dumps([expected_result]), view.answercontact_data_js)
Exemplo n.º 6
0
    def test_data_person_answercontact(self):
        # answercontact_data_js returns JSON string of a list
        # containing all contact information needed for
        # subscribers_list.js loading.
        question = self.factory.makeQuestion()
        contact = self.factory.makePerson(
            name='user', displayname='Contact Name')
        contact.addLanguage(getUtility(ILanguageSet)['en'])
        with person_logged_in(contact):
            question.target.addAnswerContact(contact, contact)
        view = create_view(question.target, '+portlet-answercontacts-details')
        api_request = IWebServiceClientRequest(view.request)

        expected_result = {
            'subscriber': {
                'name': 'user',
                'display_name': 'Contact Name',
                'is_team': False,
                'can_edit': False,
                'web_link': canonical_url(contact),
                'self_link': absoluteURL(contact, api_request)
                }
            }
        self.assertEqual(
            dumps([expected_result]), view.answercontact_data_js)
Exemplo n.º 7
0
 def test_team_admin_subscription(self):
     # Make a team subscription where the user is an admin, and see what
     # we record.
     user = self.factory.makePerson()
     target = self.factory.makeProduct()
     request = LaunchpadTestRequest()
     team = self.factory.makeTeam()
     with person_logged_in(team.teamowner):
         team.addMember(user,
                        team.teamowner,
                        status=TeamMembershipStatus.ADMIN)
         sub = target.addBugSubscription(team, team.teamowner)
     expose_user_subscriptions_to_js(user, [sub], request)
     info = IJSONRequestCache(request).objects['subscription_info']
     self.assertEqual(len(info), 1)  # One target.
     target_info = info[0]
     self.assertEqual(target_info['target_title'], target.title)
     self.assertEqual(target_info['target_url'],
                      canonical_url(target, rootsite='mainsite'))
     self.assertEqual(len(target_info['filters']), 1)  # One filter.
     filter_info = target_info['filters'][0]
     self.assertEqual(filter_info['filter'], sub.bug_filters[0])
     self.assertTrue(filter_info['subscriber_is_team'])
     self.assertTrue(filter_info['user_is_team_admin'])
     self.assertTrue(filter_info['can_mute'])
     self.assertFalse(filter_info['is_muted'])
     self.assertEqual(filter_info['subscriber_title'], team.title)
     self.assertEqual(filter_info['subscriber_link'],
                      absoluteURL(team, IWebServiceClientRequest(request)))
     self.assertEqual(filter_info['subscriber_url'],
                      canonical_url(team, rootsite='mainsite'))
Exemplo n.º 8
0
    def test_data_target_owner_answercontact_looks(self):
        # Answercontact_data_js has can_edit set to true for target owner.
        distro = self.factory.makeDistribution()
        question = self.factory.makeQuestion(target=distro)
        contact = self.factory.makePerson(
            name='user', displayname='Contact Name')
        contact.addLanguage(getUtility(ILanguageSet)['en'])
        with person_logged_in(contact):
            question.target.addAnswerContact(contact, contact)
        view = create_view(question.target, '+portlet-answercontacts-details')
        api_request = IWebServiceClientRequest(view.request)

        expected_result = {
            'subscriber': {
                'name': 'user',
                'display_name': 'Contact Name',
                'is_team': False,
                'can_edit': True,
                'web_link': canonical_url(contact),
                'self_link': absoluteURL(contact, api_request)
                }
            }
        with person_logged_in(distro.owner):
            self.assertEqual(
                dumps([expected_result]), view.answercontact_data_js)
Exemplo n.º 9
0
    def test_data_subscription_lp_admin(self):
        # For a subscription, answercontact_data_js has can_edit
        # set to true for a Launchpad admin.
        question = self.factory.makeQuestion()
        member = self.factory.makePerson()
        contact = self.factory.makePerson(
            name='user', displayname='Contact Name')
        contact.addLanguage(getUtility(ILanguageSet)['en'])
        with person_logged_in(member):
            question.target.addAnswerContact(contact, contact)
        view = create_view(question.target, '+portlet-answercontacts-details')
        api_request = IWebServiceClientRequest(view.request)

        expected_result = {
            'subscriber': {
                'name': 'user',
                'display_name': 'Contact Name',
                'is_team': False,
                'can_edit': True,
                'web_link': canonical_url(contact),
                'self_link': absoluteURL(contact, api_request)
                }
            }

        # Login as admin
        admin = getUtility(IPersonSet).find(ADMIN_EMAIL).any()
        with person_logged_in(admin):
            self.assertEqual(
                dumps([expected_result]), view.answercontact_data_js)
Exemplo n.º 10
0
    def test_data_person_subscription_subscriber(self):
        # For a subscription, subscriber_data_js has can_edit
        # set to true for the subscriber.
        bug = self._makeBugWithNoSubscribers()
        subscriber = self.factory.makePerson(name='user',
                                             displayname='Subscriber Name')
        subscribed_by = self.factory.makePerson(name='someone',
                                                displayname='Someone')
        with person_logged_in(subscriber):
            bug.subscribe(subscriber,
                          subscribed_by,
                          level=BugNotificationLevel.LIFECYCLE)
        harness = LaunchpadFormHarness(bug, BugPortletSubscribersWithDetails)
        api_request = IWebServiceClientRequest(harness.request)

        expected_result = {
            'subscriber': {
                'name': 'user',
                'display_name': 'Subscriber Name',
                'is_team': False,
                'can_edit': True,
                'web_link': canonical_url(subscriber),
                'self_link': absoluteURL(subscriber, api_request),
                'display_subscribed_by': 'Subscribed by Someone (someone)',
            },
            'subscription_level': "Lifecycle",
        }
        with person_logged_in(subscribed_by):
            self.assertEqual(dumps([expected_result]),
                             harness.view.subscriber_data_js)
Exemplo n.º 11
0
    def test_data_subscription_lp_admin(self):
        # For a subscription, subscriber_data_js has can_edit
        # set to true for a Launchpad admin.
        bug = self._makeBugWithNoSubscribers()
        member = self.factory.makePerson()
        subscriber = self.factory.makePerson(name='user',
                                             displayname='Subscriber Name')
        with person_logged_in(member):
            bug.subscribe(subscriber,
                          subscriber,
                          level=BugNotificationLevel.LIFECYCLE)
        harness = LaunchpadFormHarness(bug, BugPortletSubscribersWithDetails)
        api_request = IWebServiceClientRequest(harness.request)

        expected_result = {
            'subscriber': {
                'name': 'user',
                'display_name': 'Subscriber Name',
                'is_team': False,
                'can_edit': True,
                'web_link': canonical_url(subscriber),
                'self_link': absoluteURL(subscriber, api_request),
                'display_subscribed_by': 'Self-subscribed',
            },
            'subscription_level': "Lifecycle",
        }

        # Login as admin
        admin = getUtility(IPersonSet).find(ADMIN_EMAIL).any()
        with person_logged_in(admin):
            self.assertEqual(dumps([expected_result]),
                             harness.view.subscriber_data_js)
def expose_user_administered_teams_to_js(request,
                                         user,
                                         context,
                                         absoluteURL=absoluteURL):
    """Make the list of teams the user administers available to JavaScript."""
    # XXX: Robert Collins workaround multiple calls making this cause
    # timeouts: see bug 788510.
    objects = IJSONRequestCache(request).objects
    if 'administratedTeams' in objects:
        return
    info = []
    api_request = IWebServiceClientRequest(request)
    is_distro = IDistribution.providedBy(context)
    if is_distro:
        # If the context is a distro AND a bug supervisor is set then we only
        # allow subscriptions from members of the bug supervisor team.
        bug_supervisor = context.bug_supervisor
    else:
        bug_supervisor = None
    if user is not None:
        administrated_teams = set(user.administrated_teams)
        if administrated_teams:
            # Get this only if we need to.
            membership = set(user.teams_participated_in)
            # Only consider teams the user is both in and administers:
            #  If the user is not a member of the team itself, then
            # skip it, because structural subscriptions and their
            # filters can only be edited by the subscriber.
            # This can happen if the user is an owner but not a member.
            administers_and_in = membership.intersection(administrated_teams)
            list(
                getUtility(IPersonSet).getPrecachedPersonsFromIDs(
                    [team.id for team in administers_and_in],
                    need_preferred_email=True))

            # If the requester is the user, they're at least an admin in
            # all of these teams. Precache launchpad.(Limited)View so we
            # can see the necessary attributes.
            current_user = IPerson(get_current_principal(), None)
            if current_user is not None and user == current_user:
                for perm in ('launchpad.View', 'launchpad.LimitedView'):
                    precache_permission_for_objects(None, perm,
                                                    administers_and_in)

            for team in sorted(administers_and_in, key=attrgetter('name')):
                if (bug_supervisor is not None
                        and not team.inTeam(bug_supervisor)):
                    continue
                info.append({
                    'has_preferredemail': team.preferredemail is not None,
                    'link': absoluteURL(team, api_request),
                    'title': team.unique_displayname,
                    'url': canonical_url(team),
                })
    objects['administratedTeams'] = info
Exemplo n.º 13
0
    def test_jsoncache_contents(self):
        product = self.factory.makeProduct()
        question = self.factory.makeQuestion(target=product)
        login_person(product.owner)

        # It works even for anonymous users, so no log-in is needed.
        view = create_initialized_view(
            question.target, '+portlet-answercontacts', rootsite='answers')

        cache = IJSONRequestCache(view.request).objects
        context_url_data = {
            'web_link': canonical_url(product, rootsite='mainsite'),
            'self_link': absoluteURL(product,
                                     IWebServiceClientRequest(view.request)),
            }
        self.assertEqual(cache[product.name + '_answer_portlet_url_data'],
                         context_url_data)
def expose_user_subscriptions_to_js(user, subscriptions, request):
    """Make the user's subscriptions available to JavaScript."""
    api_request = IWebServiceClientRequest(request)
    info = {}
    if user is None:
        administered_teams = []
    else:
        administered_teams = user.administrated_teams

    for subscription in subscriptions:
        target = subscription.target
        record = info.get(target)
        if record is None:
            record = dict(target_title=target.title,
                          target_url=canonical_url(target,
                                                   rootsite='mainsite'),
                          filters=[])
            info[target] = record
        subscriber = subscription.subscriber
        for filter in subscription.bug_filters:
            is_team = subscriber.is_team
            user_is_team_admin = (is_team and subscriber in administered_teams)
            team_has_contact_address = (is_team and subscriber.preferredemail
                                        is not None)
            mailing_list = subscriber.mailing_list
            user_is_on_team_mailing_list = (
                team_has_contact_address and mailing_list is not None
                and mailing_list.is_usable
                and mailing_list.getSubscription(subscriber) is not None)
            record['filters'].append(
                dict(filter=filter,
                     subscriber_link=absoluteURL(subscriber, api_request),
                     subscriber_url=canonical_url(subscriber,
                                                  rootsite='mainsite'),
                     target_bugs_url=canonical_url(target, rootsite='bugs'),
                     subscriber_title=subscriber.title,
                     subscriber_is_team=is_team,
                     user_is_team_admin=user_is_team_admin,
                     team_has_contact_address=team_has_contact_address,
                     user_is_on_team_mailing_list=user_is_on_team_mailing_list,
                     can_mute=filter.isMuteAllowed(user),
                     is_muted=filter.muted(user) is not None,
                     target_title=target.title))
    info = info.values()
    info.sort(key=itemgetter('target_url'))
    IJSONRequestCache(request).objects['subscription_info'] = info
Exemplo n.º 15
0
 def test_self_subscription(self):
     # Make a subscription directly for the user and see what we record.
     user = self.factory.makePerson()
     target = self.factory.makeProduct()
     request = LaunchpadTestRequest()
     with person_logged_in(user):
         sub = target.addBugSubscription(user, user)
     expose_user_subscriptions_to_js(user, [sub], request)
     info = IJSONRequestCache(request).objects['subscription_info']
     filter_info = info[0]['filters'][0]
     self.assertFalse(filter_info['subscriber_is_team'])
     self.assertEqual(filter_info['subscriber_title'], user.title)
     self.assertFalse(filter_info['can_mute'])
     self.assertFalse(filter_info['is_muted'])
     self.assertEqual(filter_info['subscriber_link'],
                      absoluteURL(user, IWebServiceClientRequest(request)))
     self.assertEqual(filter_info['subscriber_url'],
                      canonical_url(user, rootsite='mainsite'))
Exemplo n.º 16
0
 def test_team_member_subscription(self):
     # Make a team subscription where the user is not an admin, and
     # see what we record.
     user = self.factory.makePerson()
     target = self.factory.makeProduct()
     request = LaunchpadTestRequest()
     team = self.factory.makeTeam(members=[user])
     with person_logged_in(team.teamowner):
         sub = target.addBugSubscription(team, team.teamowner)
     expose_user_subscriptions_to_js(user, [sub], request)
     info = IJSONRequestCache(request).objects['subscription_info']
     filter_info = info[0]['filters'][0]
     self.assertTrue(filter_info['subscriber_is_team'])
     self.assertFalse(filter_info['user_is_team_admin'])
     self.assertTrue(filter_info['can_mute'])
     self.assertFalse(filter_info['is_muted'])
     self.assertEqual(filter_info['subscriber_title'], team.title)
     self.assertEqual(filter_info['subscriber_link'],
                      absoluteURL(team, IWebServiceClientRequest(request)))
     self.assertEqual(filter_info['subscriber_url'],
                      canonical_url(team, rootsite='mainsite'))
Exemplo n.º 17
0
    def test_data_person_subscription(self):
        # subscriber_data_js returns JSON string of a list
        # containing all subscriber information needed for
        # subscribers_list.js subscribers loading.
        question = self._makeQuestionWithNoSubscribers()
        subscriber = self.factory.makePerson(name='user',
                                             displayname='Subscriber Name')
        with person_logged_in(subscriber):
            question.subscribe(subscriber, subscriber)
        view = create_view(question, '+portlet-subscribers-details')
        api_request = IWebServiceClientRequest(view.request)

        expected_result = {
            'subscriber': {
                'name': 'user',
                'display_name': 'Subscriber Name',
                'is_team': False,
                'can_edit': False,
                'web_link': canonical_url(subscriber),
                'self_link': absoluteURL(subscriber, api_request)
            },
            'subscription_level': "Direct",
        }
        self.assertEqual(dumps([expected_result]), view.subscriber_data_js)
Exemplo n.º 18
0
 def api_request(self):
     return IWebServiceClientRequest(self.request)
Exemplo n.º 19
0
    def __call__(self):
        name = self.request.form.get('name')
        if name is None:
            raise MissingInputError('name', '')

        search_text = self.request.form.get('search_text')
        if search_text is None:
            raise MissingInputError('search_text', '')
        search_filter = self.request.form.get('search_filter')

        try:
            factory = getUtility(IVocabularyFactory, name)
        except ComponentLookupError:
            raise UnexpectedFormData(
                'Unknown vocabulary %r' % name)

        vocabulary = factory(self.context)

        if IHugeVocabulary.providedBy(vocabulary):
            matches = vocabulary.searchForTerms(search_text, search_filter)
            total_size = matches.count()
        else:
            matches = list(vocabulary)
            total_size = len(matches)

        batch_navigator = BatchNavigator(matches, self.request)

        # We need to collate what IPickerEntrySource adapters are required for
        # the items in the current batch. We expect that the batch will be
        # homogenous and so only one adapter instance is required, but we
        # allow for the case where the batch may contain disparate entries
        # requiring different adapter implementations.

        # A mapping from adapter class name -> adapter instance
        adapter_cache = {}
        # A mapping from adapter class name -> list of vocab terms
        picker_entry_terms = {}
        for term in batch_navigator.currentBatch():
            picker_entry_source = IPickerEntrySource(term.value)
            adapter_class = picker_entry_source.__class__.__name__
            picker_terms = picker_entry_terms.get(adapter_class)
            if picker_terms is None:
                picker_terms = []
                picker_entry_terms[adapter_class] = picker_terms
                adapter_cache[adapter_class] = picker_entry_source
            picker_terms.append(term.value)

        # A mapping from vocab terms -> picker entries
        picker_term_entries = {}

        # For the list of terms associated with a picker adapter, we get the
        # corresponding picker entries by calling the adapter.
        for adapter_class, term_values in picker_entry_terms.items():
            picker_entries = adapter_cache[adapter_class].getPickerEntries(
                term_values,
                self.context)
            for term_value, picker_entry in izip(term_values, picker_entries):
                picker_term_entries[term_value] = picker_entry

        result = []
        for term in batch_navigator.currentBatch():
            entry = dict(value=term.token, title=term.title)
            # The canonical_url without just the path (no hostname) can
            # be passed directly into the REST PATCH call.
            api_request = IWebServiceClientRequest(self.request)
            try:
                entry['api_uri'] = canonical_url(
                    term.value, request=api_request,
                    path_only_if_possible=True)
            except NoCanonicalUrl:
                # The exception is caught, because the api_url is only
                # needed for inplace editing via a REST call. The
                # form picker doesn't need the api_url.
                entry['api_uri'] = 'Could not find canonical url.'
            picker_entry = picker_term_entries[term.value]
            if picker_entry.description is not None:
                if len(picker_entry.description) > MAX_DESCRIPTION_LENGTH:
                    entry['description'] = (
                        picker_entry.description[:MAX_DESCRIPTION_LENGTH - 3]
                        + '...')
                else:
                    entry['description'] = picker_entry.description
            if picker_entry.image is not None:
                entry['image'] = picker_entry.image
            if picker_entry.css is not None:
                entry['css'] = picker_entry.css
            if picker_entry.alt_title is not None:
                entry['alt_title'] = picker_entry.alt_title
            if picker_entry.title_link is not None:
                entry['title_link'] = picker_entry.title_link
            if picker_entry.details is not None:
                entry['details'] = picker_entry.details
            if picker_entry.alt_title_link is not None:
                entry['alt_title_link'] = picker_entry.alt_title_link
            if picker_entry.link_css is not None:
                entry['link_css'] = picker_entry.link_css
            if picker_entry.badges:
                entry['badges'] = picker_entry.badges
            if picker_entry.metadata is not None:
                entry['metadata'] = picker_entry.metadata
            if picker_entry.target_type is not None:
                entry['target_type'] = picker_entry.target_type
            result.append(entry)

        self.request.response.setHeader('Content-type', 'application/json')
        return simplejson.dumps(dict(total_size=total_size, entries=result))
Exemplo n.º 20
0
    def _test_data_private_team_subscription(self, authenticated_user):
        # For a private team subscription, the team name and url are rendered
        # for authenticated users.
        bug = self._makeBugWithNoSubscribers()

        # Set up a private direct subscriber.
        teamowner = self.factory.makePerson(name="team-owner",
                                            displayname="Team Owner")
        direct_subscriber = self.factory.makeTeam(
            name='team',
            displayname='Team Name',
            owner=teamowner,
            visibility=PersonVisibility.PRIVATE)
        with person_logged_in(teamowner):
            bug.subscribe(direct_subscriber,
                          direct_subscriber.teamowner,
                          level=BugNotificationLevel.LIFECYCLE)

        # Set up a private indirect subscriber.
        indirect_teamowner = self.factory.makePerson(
            name="indirect-team-owner", displayname="Indirect Team Owner")
        indirect_subscriber = self.factory.makeTeam(
            name='indirect-team',
            displayname='Indirect Team Name',
            owner=indirect_teamowner,
            visibility=PersonVisibility.PRIVATE)
        with person_logged_in(indirect_teamowner):
            bug.default_bugtask.target.addSubscription(indirect_subscriber,
                                                       indirect_teamowner)

        request = LaunchpadTestRequest()
        expected_result = []
        view = create_initialized_view(bug,
                                       '+bug-portlet-subscribers-details',
                                       request=request)
        if authenticated_user:
            any_person = self.factory.makePerson()
            login_person(any_person, request)
            api_request = IWebServiceClientRequest(request)
            naked_subscriber = removeSecurityProxy(direct_subscriber)
            naked_indirect_subscriber = removeSecurityProxy(
                indirect_subscriber)
            expected_result = [{
                'subscriber': {
                    'name': 'team',
                    'display_name': 'Team Name',
                    'is_team': True,
                    'can_edit': False,
                    'web_link': canonical_url(naked_subscriber,
                        rootsite='mainsite'),
                    'self_link': absoluteURL(naked_subscriber, api_request),
                    'display_subscribed_by': \
                        'Subscribed by Team Owner (team-owner)',
                    },
                'subscription_level': "Lifecycle",
                },
                {
                'subscriber': {
                    'name': 'indirect-team',
                    'display_name': 'Indirect Team Name',
                    'is_team': True,
                    'can_edit': False,
                    'web_link': canonical_url(naked_indirect_subscriber,
                        rootsite='mainsite'),
                    'self_link': absoluteURL(
                        naked_indirect_subscriber, api_request),
                    },
                'subscription_level': "Maybe",
                }]
        self.assertEqual(dumps(expected_result), view.subscriber_data_js)