~launchpad-pqm/launchpad/devel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# Copyright 2010 Canonical Ltd.  This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).

__metaclass__ = type

from zope.component import getUtility
from zope.security.proxy import removeSecurityProxy

from canonical.launchpad.testing.pages import (
    extract_text,
    find_tag_by_id,
    )
from canonical.launchpad.webapp.publisher import canonical_url
from canonical.testing.layers import DatabaseFunctionalLayer
from lp.registry.browser.team import TeamOverviewMenu
from lp.registry.interfaces.person import PersonVisibility
from lp.registry.interfaces.persontransferjob import IPersonMergeJobSource
from lp.registry.interfaces.teammembership import (
    ITeamMembershipSet,
    TeamMembershipStatus,
    )
from lp.testing import (
    login_person,
    person_logged_in,
    TestCaseWithFactory,
    )
from lp.testing.matchers import IsConfiguredBatchNavigator
from lp.testing.menu import check_menu_links
from lp.testing.views import (
    create_initialized_view,
    create_view,
    )


class TestTeamMenu(TestCaseWithFactory):

    layer = DatabaseFunctionalLayer

    def setUp(self):
        super(TestTeamMenu, self).setUp()
        self.team = self.factory.makeTeam()

    def test_TeamOverviewMenu_check_menu_links_without_mailing(self):
        menu = TeamOverviewMenu(self.team)
        # Remove moderate_mailing_list because it asserts that there is
        # a mailing list.
        no_mailinst_list_links = [
            link for link in menu.links if link != 'moderate_mailing_list']
        menu.links = no_mailinst_list_links
        self.assertEqual(True, check_menu_links(menu))
        link = menu.configure_mailing_list()
        self.assertEqual('Create a mailing list', link.text)

    def test_TeamOverviewMenu_check_menu_links_with_mailing(self):
        self.factory.makeMailingList(
            self.team, self.team.teamowner)
        menu = TeamOverviewMenu(self.team)
        self.assertEqual(True, check_menu_links(menu))
        link = menu.configure_mailing_list()
        self.assertEqual('Configure mailing list', link.text)


class TestModeration(TestCaseWithFactory):

    layer = DatabaseFunctionalLayer

    def test_held_messages_is_batch_navigator(self):
        team = self.factory.makeTeam()
        self.factory.makeMailingList(team, team.teamowner)
        view = create_initialized_view(team, name='+mailinglist-moderate')
        self.assertThat(
            view.held_messages,
            IsConfiguredBatchNavigator('message', 'messages'))

    def test_no_mailing_list_redirect(self):
        team = self.factory.makeTeam()
        login_person(team.teamowner)
        view = create_view(team, name='+mailinglist-moderate')
        response = view.request.response
        self.assertEqual(302, response.getStatus())
        self.assertEqual(canonical_url(team), response.getHeader('location'))
        self.assertEqual(1, len(response.notifications))
        self.assertEqual(
            '%s does not have a mailing list.' % (team.displayname),
            response.notifications[0].message)


class TestTeamMemberAddView(TestCaseWithFactory):

    layer = DatabaseFunctionalLayer

    def setUp(self):
        super(TestTeamMemberAddView, self).setUp()
        self.team = self.factory.makeTeam(name='test-team')
        login_person(self.team.teamowner)

    def getForm(self, new_member):
        return {
            'field.newmember': new_member.name,
            'field.actions.add': 'Add Member',
            }

    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_add_former_member_success(self):
        member = self.factory.makePerson(name="a-member")
        self.team.addMember(member, self.team.teamowner)
        with person_logged_in(member):
            member.leave(self.team)
        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))

    def test_add_existing_member_fail(self):
        member = self.factory.makePerson(name="a-member")
        self.team.addMember(member, self.team.teamowner)
        form = self.getForm(member)
        view = create_initialized_view(self.team, "+addmember", form=form)
        self.assertEqual(1, len(view.errors))
        self.assertEqual(
            "A-member (a-member) is already a member of Test Team.",
            view.errors[0])

    def test_add_empty_team_fail(self):
        empty_team = self.factory.makeTeam(owner=self.team.teamowner)
        self.team.teamowner.leave(empty_team)
        form = self.getForm(empty_team)
        view = create_initialized_view(self.team, "+addmember", form=form)
        self.assertEqual(1, len(view.errors))
        self.assertEqual(
            "You can't add a team that doesn't have any active members.",
            view.errors[0])

    def test_no_TeamMembershipTransitionError(self):
        # Attempting to add a team never triggers a
        # TeamMembershipTransitionError
        member_team = self.factory.makeTeam()
        self.team.addMember(member_team, self.team.teamowner)
        tm = getUtility(ITeamMembershipSet).getByPersonAndTeam(
            member_team, self.team)
        for status in TeamMembershipStatus.items:
            removeSecurityProxy(tm).status = status
            view = create_initialized_view(self.team, "+addmember")
            view.add_action.success(data={'newmember': member_team})


class TestTeamIndexView(TestCaseWithFactory):

    layer = DatabaseFunctionalLayer

    def setUp(self):
        super(TestTeamIndexView, self).setUp()
        self.team = self.factory.makeTeam(name='test-team')
        login_person(self.team.teamowner)

    def test_add_member_step_title(self):
        view = create_initialized_view(self.team, '+index')
        self.assertEqual('Search', view.add_member_step_title)

    def test_is_merge_pending(self):
        target_team = self.factory.makeTeam()
        job_source = getUtility(IPersonMergeJobSource)
        job_source.create(
            from_person=self.team, to_person=target_team,
            reviewer=target_team.teamowner)
        view = create_initialized_view(self.team, name="+index")
        notifications = view.request.response.notifications
        message = (
            'Test Team is queued to be be merged or deleted '
            'in a few minutes.')
        self.assertEqual(1, len(notifications))
        self.assertEqual(message, notifications[0].message)

    def test_user_without_launchpad_view(self):
        # When the user does not have launchpad.View on the context,
        user = self.factory.makePerson()
        owner = self.factory.makePerson()
        with person_logged_in(owner):
            team = self.factory.makeTeam(
                displayname='Waffles', owner=owner,
                visibility=PersonVisibility.PRIVATE)
            archive = self.factory.makeArchive(private=True, owner=team)
            archive.newSubscription(user, registrant=owner)
        with person_logged_in(user):
            view = create_initialized_view(
                team, name="+index",  server_url=canonical_url(team),
                path_info='', principal=user)
            document = find_tag_by_id(view(), 'document')
        self.assertIsNone(document.find(True, id='side-portlets'))
        self.assertIsNone(document.find(True, id='registration'))
        self.assertEndsWith(
            extract_text(document.find(True, id='maincontent')),
            'The information in this page is not shared with you.')