~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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
SourcePackage views
===================

Edit packaging view
-------------------

    >>> product = factory.makeProduct(name='bonkers', displayname='Bonkers')
    >>> productseries = factory.makeProductSeries(
    ...     name='crazy', product=product)
    >>> distribution = factory.makeDistribution(
    ...     name='youbuntu', displayname='Youbuntu')
    >>> distroseries = factory.makeDistroRelease(name='busy',
    ...     distribution=distribution)
    >>> sourcepackagename = factory.makeSourcePackageName(name='bonkers')
    >>> package = factory.makeSourcePackage(
    ...     sourcepackagename=sourcepackagename, distroseries=distroseries)

    >>> view = create_initialized_view(package, name='+edit-packaging')
    >>> print view.label
    Link to an upstream project

    >>> print view.page_title
    Link to an upstream project

    >>> print view.view.cancel_url
    http://launchpad.dev/youbuntu/busy/+source/bonkers


The view allows the logged in user to change product series field. The
value of the product field is None by default because it is not required
to create a source package.

    # The product field is added in setUpFields().
    >>> view.view.field_names
    ['__visited_steps__']
    >>> [form_field.__name__ for form_field in view.view.form_fields]
    ['__visited_steps__', 'product']

    >>> print view.view.widgets.get('product')._getFormValue()
    <BLANKLINE>

    >>> print package.productseries
    None

This is a multistep view. In the first step, the product is specified.

    >>> print view.view.__class__.__name__
    SourcePackageChangeUpstreamStepOne
    >>> print view.view.request.form
    {'field.__visited_steps__': 'sourcepackage_change_upstream_step1'}

    >>> login_person(product.owner)
    >>> form = {
    ...     'field.product': 'bonkers',
    ...     'field.actions.continue': 'Continue',
    ...     }
    >>> form.update(view.view.request.form)
    >>> view = create_initialized_view(
    ...     package, name='+edit-packaging', form=form,
    ...     principal=product.owner)
    >>> view.view.errors
    []

In the second step, one of the series of the previously selected
product can be chosen from a list of options.

    >>> print view.view.__class__.__name__
    SourcePackageChangeUpstreamStepTwo
    >>> print view.view.request.form['field.__visited_steps__']
    sourcepackage_change_upstream_step1|sourcepackage_change_upstream_step2
    >>> [term.token for term in view.view.widgets['productseries'].vocabulary]
    ['trunk', 'crazy']

    >>> form = {
    ...     'field.__visited_steps__': 'sourcepackage_change_upstream_step2',
    ...     'field.product': 'bonkers',
    ...     'field.productseries': 'crazy',
    ...     'field.actions.continue': 'continue',
    ...     }
    >>> view = create_initialized_view(
    ...     package, name='+edit-packaging', form=form,
    ...     principal=product.owner)

    >>> ignored = view.view.render()
    >>> print view.view.next_url
    http://launchpad.dev/youbuntu/busy/+source/bonkers

    >>> for notification in view.request.response.notifications:
    ...     print notification.message
    Upstream link updated.

    >>> print package.productseries.name
    crazy

    >>> transaction.commit()

The form shows the current product if it is set.

    >>> view = create_initialized_view(package, name='+edit-packaging')

    >>> print view.view.widgets.get('product')._getFormValue().name
    bonkers

If the same product as the current product series is selected,
then the current product series will be the selected option.

    >>> form = {
    ...     'field.product': 'bonkers',
    ...     'field.actions.continue': 'Continue',
    ...     }
    >>> form.update(view.view.request.form)
    >>> view = create_initialized_view(
    ...     package, name='+edit-packaging', form=form,
    ...     principal=product.owner)
    >>> print view.view.widgets.get('productseries')._getFormValue().name
    crazy

The form requires a product. An error is raised if the field is left
empty.

    >>> form = {
    ...     'field.__visited_steps__': 'sourcepackage_change_upstream_step1',
    ...     'field.product': '',
    ...     'field.actions.continue': 'Continue',
    ...     }
    >>> view = create_initialized_view(
    ...     package, name='+edit-packaging', form=form,
    ...     principal=product.owner)
    >>> for error in view.view.errors:
    ...     print error
    ('product', u'Project', RequiredMissing())

Submitting the same product series as the current packaging is not an error,
but there is no notification message that the upstream link was updated.

    >>> form = {
    ...     'field.__visited_steps__': 'sourcepackage_change_upstream_step2',
    ...     'field.product': 'bonkers',
    ...     'field.productseries': 'crazy',
    ...     'field.actions.continue': 'Continue',
    ...     }
    >>> view = create_initialized_view(
    ...     package, name='+edit-packaging', form=form,
    ...     principal=product.owner)
    >>> print view.view
    <...SourcePackageChangeUpstreamStepTwo object...>
    >>> print view.view.next_url
    http://launchpad.dev/youbuntu/busy/+source/bonkers
    >>> view.view.errors
    []

    >>> print view.request.response.notifications
    []


Upstream associations portlet
-----------------------------

The upstreams associations portlet either displays the upstream
information if it is already set or gives the user the opportunity to
suggest the association.  The suggestion is based on a
ProductVocabulary query using the source package name.

Since the bonkers source project was associated previously with the
bonkers project, the portlet will display that information.

    >>> view = create_initialized_view(package, name='+portlet-associations')
    >>> for product in view.product_suggestions:
    ...     print product.name
    bonkers

    >>> from canonical.launchpad.testing.pages import (
    ...     extract_text, find_tag_by_id)
    >>> content = find_tag_by_id(view.render(), 'upstreams')
    >>> for link in content.findAll('a'):
    ...     print link['href']
    /bonkers
    /bonkers/crazy
    .../+source/bonkers/+edit-packaging
    .../+source/bonkers/+remove-packaging

    >>> print extract_text(content)
    Bonkers...crazy...
    Bug supervisor: no
    Bug tracker: no
    Branch: no
    There are no registered releases for the Bonkers &rArr; crazy.

A new source project that is not linked to an upstream will result in
the portlet showing the suggested project.

    >>> product = factory.makeProduct(name='lernid', displayname='Lernid')
    >>> sourcepackagename = factory.makeSourcePackageName(name='lernid')
    >>> package = factory.makeSourcePackage(
    ...     sourcepackagename=sourcepackagename, distroseries=distroseries)

    >>> view = create_initialized_view(package, name='+portlet-associations')
    >>> for product in view.product_suggestions:
    ...     print product.name
    lernid

    >>> content = extract_text(find_tag_by_id(view.render(), 'no-upstreams'))
    >>> print content
    Launchpad doesn&#8217;t know which project and series this
    package belongs to. ...
    Is the following project the upstream for this source package?
    Registered upstream project:
    Lernid
    Choose another upstream project
    Register the upstream project

The form does not steal focus because it is not the primary purpose of the
page.

    >>> print view.initial_focus_widget
    None

If there are multiple potential matches, the first 9 are shown. The 10th
item is reserved for the "Choose another upstream project" option.

    >>> product = factory.makeProduct(
    ...     name='lernid-dev', displayname='Lernid Dev')
    >>> view = create_initialized_view(package, name='+portlet-associations')
    >>> for product in view.product_suggestions:
    ...     print product.name
    lernid
    lernid-dev

    >>> view.max_suggestions
    9

    >>> content = extract_text(find_tag_by_id(view.render(), 'no-upstreams'))
    >>> print content
    Launchpad doesn&#8217;t know which project and series this
    package belongs to. ...
    Is one of these projects the upstream for this source package?
    Registered upstream project:
    Lernid...
    Lernid Dev...
    Choose another upstream project
    Register the upstream project

Choosing the "Choose another upstream project" option redirects the user
to the +edit-packaging page where the user can search for a project.

    >>> form = {
    ...     'field.upstream': 'OTHER_UPSTREAM',
    ...     'field.actions.link': 'Link to Upstream Project',
    ...     }
    >>> view = create_initialized_view(
    ...     package, name='+portlet-associations', form=form)
    >>> view.errors
    []
    >>> print view.next_url
    http://launchpad.dev/youbuntu/busy/+source/lernid/+edit-packaging


Upstream connections view
-------------------------

The view includes a property for determining if the project has a bug
tracker, though the rules are somewhat complicated.

If the view's package has no productseries set then has_bugtracker is False.


    >>> product = factory.makeProduct(name='stinky', displayname='Stinky')
    >>> productseries = factory.makeProductSeries(
    ...     name='stinkyseries', product=product)
    >>> distroseries = factory.makeDistroRelease(name='wonky',
    ...     distribution=distribution)
    >>> sourcepackagename = factory.makeSourcePackageName(
    ...     name='stinkypackage')
    >>> package = factory.makeSourcePackage(
    ...     sourcepackagename=sourcepackagename, distroseries=distroseries)

    >>> view = create_initialized_view(
    ...     package, name='+upstream-connections')

    >>> print package.productseries
    None
    >>> print view.has_bugtracker
    False

So let's set the product series so we can do more interesting testing.

    >>> package.setPackaging(productseries, product.owner)
    >>> print package.productseries.name
    stinkyseries

If a product is not part of a project group and its bug tracker is not
set then the view property is false.

    >>> view = create_initialized_view(
    ...     package, name='+upstream-connections')

    >>> print product.bug_tracking_usage.name
    UNKNOWN
    >>> print product.bugtracker
    None
    >>> print view.has_bugtracker
    False

Having official_malone set results in has_bugtracker being true.

    >>> login_person(product.owner)
    >>> product.official_malone = True
    >>> print view.has_bugtracker
    True

Having a bug_tracker set also results in has_bugtracker being true (a
bit of a tautology you'd think).

    >>> product.official_malone = False
    >>> bugtracker = factory.makeBugTracker()
    >>> product.bugtracker = bugtracker
    >>> print view.has_bugtracker
    True

If the product has no bug tracker and is in a project group with no
bug tracker then the property is false.

    >>> product.bugtracker = None
    >>> project = factory.makeProject()
    >>> print project.bugtracker
    None
    >>> product.project = project
    >>> print view.has_bugtracker
    False

If the product's project does have a bug tracker then the product
inherits it.

    >>> login_person(project.owner)
    >>> project.bugtracker = bugtracker
    >>> print view.has_bugtracker
    True


Remove packaging view
---------------------

This view allows removal of the packaging link from the sourcepackage
to the project series.

    >>> view = create_initialized_view(package, name='+remove-packaging')
    >>> print view.label
    Unlink an upstream project

    >>> print view.page_title
    Unlink an upstream project

    >>> print view.cancel_url
    http://launchpad.dev/youbuntu/wonky/+source/stinkypackage

    >>> user = package.packaging.owner
    >>> login_person(user)
    >>> form = {'field.actions.unlink': 'Unlink'}
    >>> view = create_initialized_view(
    ...     package, name='+remove-packaging', form=form, principal=user)
    >>> view.errors
    []

    >>> for notification in view.request.response.notifications:
    ...     print notification.message
    Removed upstream association between Stinky stinkyseries series and Wonky.

If somebody attempts to remove this packaging link a second time,
they get a message telling them that the link has already been
deleted.

    >>> view = create_initialized_view(
    ...     package, name='+remove-packaging', form=form, principal=user)
    >>> view.errors
    []

    >>> for notification in view.request.response.notifications:
    ...     print notification.message
    The packaging link has already been deleted.

    >>> view = create_initialized_view(package, name='+portlet-associations')
    >>> print extract_text(find_tag_by_id(view.render(), 'no-upstreams'))
    Launchpad doesn&#8217;t know which project ...
    There are no projects registered in Launchpad that are a potential
    match for this source package. Can you help us find one?
    Registered upstream project:
    Choose another upstream project
    Register the upstream project