Merge lp:~cjwatson/launchpad/potemplate-dsp-vocab into lp:launchpad
- potemplate-dsp-vocab
- Merge into devel
Proposed by
Colin Watson
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Merged at revision: | 18199 | ||||||||
Proposed branch: | lp:~cjwatson/launchpad/potemplate-dsp-vocab | ||||||||
Merge into: | lp:launchpad | ||||||||
Prerequisite: | lp:~cjwatson/launchpad/productseries-ubuntupkg-dsp-vocab | ||||||||
Diff against target: |
583 lines (+347/-28) 8 files modified
lib/lp/app/widgets/popup.py (+8/-0) lib/lp/app/widgets/templates/distributionsourcepackage-picker.pt (+5/-0) lib/lp/bugs/browser/widgets/bugtask.py (+1/-2) lib/lp/bugs/doc/bugtask-package-widget.txt (+18/-21) lib/lp/translations/browser/potemplate.py (+51/-2) lib/lp/translations/browser/tests/test_potemplate_views.py (+68/-3) lib/lp/translations/browser/widgets/potemplate.py (+62/-0) lib/lp/translations/browser/widgets/tests/test_potemplate.py (+134/-0) |
||||||||
To merge this branch: | bzr merge lp:~cjwatson/launchpad/potemplate-dsp-vocab | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
William Grant | code | Approve | |
Review via email: mp+305490@code.launchpad.net |
Commit message
Convert POTemplate:+edit and POTemplate:+admin to use the DistributionSou
Description of the change
Convert POTemplate:+edit and POTemplate:+admin to use the DistributionSou
We need another hack in the picker setup to cope with getting the distribution from the distroseries field, and we have to be a bit more careful about how we process empty forms so that GET requests work properly, but the rest is fairly straightforward.
To post a comment you must log in.
Revision history for this message
William Grant (wgrant) : | # |
review:
Approve
(code)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/app/widgets/popup.py' |
2 | --- lib/lp/app/widgets/popup.py 2016-09-12 15:29:11 +0000 |
3 | +++ lib/lp/app/widgets/popup.py 2016-09-12 15:29:12 +0000 |
4 | @@ -305,6 +305,7 @@ |
5 | return self._prefix + 'distribution' |
6 | |
7 | distribution_name = '' |
8 | + distroseries_id = '' |
9 | |
10 | |
11 | class SourcePackageNameWidgetBase(DistributionSourcePackagePickerWidget): |
12 | @@ -325,6 +326,13 @@ |
13 | super(SourcePackageNameWidgetBase, self).__init__( |
14 | field, vocabulary, request) |
15 | self.cached_values = {} |
16 | + if bool(getFeatureFlag('disclosure.dsp_picker.enabled')): |
17 | + # The distribution may change later when we process form input, |
18 | + # but setting it here makes it easier to construct some views, |
19 | + # particularly edit views where we need to render the context. |
20 | + distribution = self.getDistribution() |
21 | + if distribution is not None: |
22 | + self.context.vocabulary.setDistribution(distribution) |
23 | |
24 | def getDistribution(self): |
25 | """Get the distribution used for package validation. |
26 | |
27 | === modified file 'lib/lp/app/widgets/templates/distributionsourcepackage-picker.pt' |
28 | --- lib/lp/app/widgets/templates/distributionsourcepackage-picker.pt 2016-07-21 20:22:00 +0000 |
29 | +++ lib/lp/app/widgets/templates/distributionsourcepackage-picker.pt 2016-09-12 15:29:12 +0000 |
30 | @@ -9,6 +9,7 @@ |
31 | var config = ${view/json_config}; |
32 | var distribution_name = '${view/distribution_name}'; |
33 | var distribution_id = '${view/distribution_id}'; |
34 | + var distroseries_id = '${view/distroseries_id}'; |
35 | if (distribution_name !== '') { |
36 | config.getContextPath = function() { |
37 | return '/' + distribution_name; |
38 | @@ -17,6 +18,10 @@ |
39 | config.getContextPath = function() { |
40 | return '/' + Y.DOM.byId(distribution_id).value; |
41 | }; |
42 | + } else if (distroseries_id !== '') { |
43 | + config.getContextPath = function() { |
44 | + return '/' + Y.DOM.byId(distroseries_id).value.split('/', 2)[0]; |
45 | + }; |
46 | } |
47 | var show_widget_id = '${view/show_widget_id}'; |
48 | Y.on('domready', function(e) { |
49 | |
50 | === modified file 'lib/lp/bugs/browser/widgets/bugtask.py' |
51 | --- lib/lp/bugs/browser/widgets/bugtask.py 2016-09-12 15:29:11 +0000 |
52 | +++ lib/lp/bugs/browser/widgets/bugtask.py 2016-09-12 15:29:12 +0000 |
53 | @@ -505,8 +505,7 @@ |
54 | """See `SourcePackageNameWidgetBase`.""" |
55 | distribution_name = self.request.form.get('field.distribution') |
56 | if distribution_name is None: |
57 | - raise UnexpectedFormData( |
58 | - "field.distribution wasn't in the request") |
59 | + return None |
60 | distribution = getUtility(IDistributionSet).getByName( |
61 | distribution_name) |
62 | if distribution is None: |
63 | |
64 | === modified file 'lib/lp/bugs/doc/bugtask-package-widget.txt' |
65 | --- lib/lp/bugs/doc/bugtask-package-widget.txt 2016-09-12 15:29:11 +0000 |
66 | +++ lib/lp/bugs/doc/bugtask-package-widget.txt 2016-09-12 15:29:12 +0000 |
67 | @@ -118,33 +118,30 @@ |
68 | >>> request = LaunchpadTestRequest( |
69 | ... form={'field.distribution': 'debian', |
70 | ... 'field.sourcepackagename': 'linux-2.6.12'}) |
71 | - >>> widget = BugTaskAlsoAffectsSourcePackageNameWidget( |
72 | - ... package_field, package_field.vocabulary, request) |
73 | - >>> widget.getDistribution().name |
74 | + >>> BugTaskAlsoAffectsSourcePackageNameWidget( |
75 | + ... package_field, package_field.vocabulary, |
76 | + ... request).getDistribution().name |
77 | u'debian' |
78 | |
79 | -+distrotask always supplies a valid distribution name. If the widget |
80 | -doesn't get a name, or the name isn't the name of a distro, |
81 | -UnexpectedFormData is raised. |
82 | ++distrotask always supplies a valid distribution name or none at all. If the |
83 | +name isn't the name of a distro, UnexpectedFormData is raised. |
84 | |
85 | >>> request = LaunchpadTestRequest( |
86 | ... form={'field.distribution': 'non-existing', |
87 | ... 'field.sourcepackagename': 'linux-2.6.12'}) |
88 | - >>> widget = BugTaskAlsoAffectsSourcePackageNameWidget( |
89 | - ... package_field, package_field.vocabulary, request) |
90 | - >>> widget.getDistribution().name |
91 | - Traceback (most recent call last): |
92 | - ... |
93 | - UnexpectedFormData: ... |
94 | - |
95 | - >>> request = LaunchpadTestRequest( |
96 | - ... form={'field.sourcepackagename': 'linux-2.6.12'}) |
97 | - >>> widget = BugTaskAlsoAffectsSourcePackageNameWidget( |
98 | - ... package_field, package_field.vocabulary, request) |
99 | - >>> widget.getDistribution().name |
100 | - Traceback (most recent call last): |
101 | - ... |
102 | - UnexpectedFormData: ... |
103 | + >>> BugTaskAlsoAffectsSourcePackageNameWidget( |
104 | + ... package_field, package_field.vocabulary, |
105 | + ... request).getDistribution().name |
106 | + Traceback (most recent call last): |
107 | + ... |
108 | + UnexpectedFormData: ... |
109 | + |
110 | +A GET request usually won't supply a distribution name at all. |
111 | + |
112 | + >>> request = LaunchpadTestRequest(form={}) |
113 | + >>> BugTaskAlsoAffectsSourcePackageNameWidget( |
114 | + ... package_field, package_field.vocabulary, |
115 | + ... request).getDistribution() |
116 | |
117 | |
118 | FileBugSourcePackageNameWidget |
119 | |
120 | === modified file 'lib/lp/translations/browser/potemplate.py' |
121 | --- lib/lp/translations/browser/potemplate.py 2016-06-09 20:13:17 +0000 |
122 | +++ lib/lp/translations/browser/potemplate.py 2016-09-12 15:29:12 +0000 |
123 | @@ -1,4 +1,4 @@ |
124 | -# Copyright 2009-2012 Canonical Ltd. This software is licensed under the |
125 | +# Copyright 2009-2016 Canonical Ltd. This software is licensed under the |
126 | # GNU Affero General Public License version 3 (see the file LICENSE). |
127 | """Browser code for PO templates.""" |
128 | |
129 | @@ -26,6 +26,7 @@ |
130 | import operator |
131 | import os.path |
132 | |
133 | +from lazr.restful.interface import copy_field |
134 | from lazr.restful.utils import smartquote |
135 | import pytz |
136 | from storm.expr import ( |
137 | @@ -41,6 +42,7 @@ |
138 | from lp import _ |
139 | from lp.app.browser.launchpadform import ( |
140 | action, |
141 | + custom_widget, |
142 | LaunchpadEditFormView, |
143 | ReturnToReferrerMixin, |
144 | ) |
145 | @@ -51,11 +53,15 @@ |
146 | ) |
147 | from lp.app.errors import NotFoundError |
148 | from lp.app.validators.name import valid_name |
149 | +from lp.registry.interfaces.distributionsourcepackage import ( |
150 | + IDistributionSourcePackage, |
151 | + ) |
152 | from lp.registry.interfaces.role import IPersonRoles |
153 | from lp.registry.model.packaging import Packaging |
154 | from lp.registry.model.product import Product |
155 | from lp.registry.model.productseries import ProductSeries |
156 | from lp.registry.model.sourcepackagename import SourcePackageName |
157 | +from lp.services.features import getFeatureFlag |
158 | from lp.services.helpers import is_tar_filename |
159 | from lp.services.propertycache import cachedproperty |
160 | from lp.services.webapp import ( |
161 | @@ -86,6 +92,10 @@ |
162 | from lp.translations.browser.translationsharing import ( |
163 | TranslationSharingDetailsMixin, |
164 | ) |
165 | +from lp.translations.browser.widgets.potemplate import ( |
166 | + POTemplateAdminSourcePackageNameWidget, |
167 | + POTemplateEditSourcePackageNameWidget, |
168 | + ) |
169 | from lp.translations.interfaces.pofile import IPOFileSet |
170 | from lp.translations.interfaces.potemplate import ( |
171 | IPOTemplate, |
172 | @@ -492,10 +502,29 @@ |
173 | return POTemplateView.pofiles(self, preferred_only=True) |
174 | |
175 | |
176 | +class IPOTemplateEditForm(IPOTemplate): |
177 | + |
178 | + sourcepackagename = copy_field( |
179 | + IPOTemplate['sourcepackagename'], |
180 | + vocabularyName='DistributionSourcePackage') |
181 | + |
182 | + from_sourcepackagename = copy_field( |
183 | + IPOTemplate['from_sourcepackagename'], |
184 | + vocabularyName='DistributionSourcePackage') |
185 | + |
186 | + |
187 | class POTemplateEditView(ReturnToReferrerMixin, LaunchpadEditFormView): |
188 | """View class that lets you edit a POTemplate object.""" |
189 | |
190 | - schema = IPOTemplate |
191 | + @property |
192 | + def schema(self): |
193 | + """See `LaunchpadFormView`.""" |
194 | + if bool(getFeatureFlag('disclosure.dsp_picker.enabled')): |
195 | + return IPOTemplateEditForm |
196 | + else: |
197 | + return IPOTemplate |
198 | + |
199 | + custom_widget('sourcepackagename', POTemplateEditSourcePackageNameWidget) |
200 | label = 'Edit translation template details' |
201 | page_title = 'Edit details' |
202 | PRIORITY_MIN_VALUE = 0 |
203 | @@ -516,6 +545,14 @@ |
204 | return field_names |
205 | |
206 | @property |
207 | + def adapters(self): |
208 | + """See `LaunchpadFormView`.""" |
209 | + if bool(getFeatureFlag('disclosure.dsp_picker.enabled')): |
210 | + return {IPOTemplateEditForm: self.context} |
211 | + else: |
212 | + return {} |
213 | + |
214 | + @property |
215 | def _return_url(self): |
216 | # We override the ReturnToReferrerMixin _return_url because it might |
217 | # change when any of the productseries, distroseries, |
218 | @@ -548,6 +585,9 @@ |
219 | context.setActive(iscurrent) |
220 | old_description = context.description |
221 | old_translation_domain = context.translation_domain |
222 | + for field in ('sourcepackagename', 'from_sourcepackagename'): |
223 | + if IDistributionSourcePackage.providedBy(data.get(field)): |
224 | + data[field] = data[field].sourcepackagename |
225 | self.updateContextFromData(data) |
226 | if old_description != context.description: |
227 | self.user.assignKarma( |
228 | @@ -565,6 +605,8 @@ |
229 | """Return a POTemplateSubset corresponding to the chosen target.""" |
230 | sourcepackagename = data.get('sourcepackagename', |
231 | self.context.sourcepackagename) |
232 | + if IDistributionSourcePackage.providedBy(sourcepackagename): |
233 | + sourcepackagename = sourcepackagename.sourcepackagename |
234 | return getUtility(IPOTemplateSet).getSubset( |
235 | distroseries=self.context.distroseries, |
236 | sourcepackagename=sourcepackagename, |
237 | @@ -582,6 +624,8 @@ |
238 | distroseries = data.get('distroseries', self.context.distroseries) |
239 | sourcepackagename = data.get( |
240 | 'sourcepackagename', self.context.sourcepackagename) |
241 | + if IDistributionSourcePackage.providedBy(sourcepackagename): |
242 | + sourcepackagename = sourcepackagename.sourcepackagename |
243 | productseries = data.get('productseries', None) |
244 | sourcepackage_changed = ( |
245 | distroseries is not None and |
246 | @@ -656,6 +700,9 @@ |
247 | 'from_sourcepackagename', 'sourcepackageversion', |
248 | 'languagepack', 'path', 'source_file_format', 'priority', |
249 | 'date_last_updated'] |
250 | + custom_widget('sourcepackagename', POTemplateAdminSourcePackageNameWidget) |
251 | + custom_widget( |
252 | + 'from_sourcepackagename', POTemplateAdminSourcePackageNameWidget) |
253 | label = 'Administer translation template' |
254 | page_title = "Administer" |
255 | |
256 | @@ -663,6 +710,8 @@ |
257 | """Return a POTemplateSubset corresponding to the chosen target.""" |
258 | distroseries = data.get('distroseries') |
259 | sourcepackagename = data.get('sourcepackagename') |
260 | + if IDistributionSourcePackage.providedBy(sourcepackagename): |
261 | + sourcepackagename = sourcepackagename.sourcepackagename |
262 | productseries = data.get('productseries') |
263 | |
264 | if distroseries is not None and productseries is not None: |
265 | |
266 | === modified file 'lib/lp/translations/browser/tests/test_potemplate_views.py' |
267 | --- lib/lp/translations/browser/tests/test_potemplate_views.py 2012-12-10 13:43:47 +0000 |
268 | +++ lib/lp/translations/browser/tests/test_potemplate_views.py 2016-09-12 15:29:12 +0000 |
269 | @@ -1,25 +1,46 @@ |
270 | -# Copyright 2011 Canonical Ltd. This software is licensed under the |
271 | +# Copyright 2011-2016 Canonical Ltd. This software is licensed under the |
272 | # GNU Affero General Public License version 3 (see the file LICENSE). |
273 | |
274 | """Module doc.""" |
275 | |
276 | __metaclass__ = type |
277 | |
278 | +from testscenarios import ( |
279 | + load_tests_apply_scenarios, |
280 | + WithScenarios, |
281 | + ) |
282 | |
283 | +from lp.services.features.testing import FeatureFixture |
284 | from lp.services.webapp.escaping import html_escape |
285 | from lp.services.webapp.servers import LaunchpadTestRequest |
286 | -from lp.testing import TestCaseWithFactory |
287 | +from lp.testing import ( |
288 | + celebrity_logged_in, |
289 | + TestCaseWithFactory, |
290 | + ) |
291 | from lp.testing.layers import DatabaseFunctionalLayer |
292 | +from lp.testing.views import create_initialized_view |
293 | from lp.translations.browser.potemplate import ( |
294 | POTemplateAdminView, |
295 | POTemplateEditView, |
296 | ) |
297 | |
298 | |
299 | -class TestPOTemplateEditViewValidation(TestCaseWithFactory): |
300 | +class TestPOTemplateEditViewValidation(WithScenarios, TestCaseWithFactory): |
301 | |
302 | layer = DatabaseFunctionalLayer |
303 | |
304 | + scenarios = [ |
305 | + ("spn_picker", {"features": {}}), |
306 | + ("dsp_picker", { |
307 | + "features": {u"disclosure.dsp_picker.enabled": u"on"}, |
308 | + }), |
309 | + ] |
310 | + |
311 | + def setUp(self): |
312 | + super(TestPOTemplateEditViewValidation, self).setUp() |
313 | + if self.features: |
314 | + self.useFixture(FeatureFixture(self.features)) |
315 | + |
316 | def _makeData(self, potemplate, **kwargs): |
317 | """Create form data for the given template with some changed values. |
318 | |
319 | @@ -131,6 +152,23 @@ |
320 | [u'Source package already has a template with that same domain.'], |
321 | view.errors) |
322 | |
323 | + def test_change_sourcepackage(self): |
324 | + # Changing the source package is honoured. |
325 | + distroseries = self.factory.makeDistroSeries() |
326 | + potemplate = self.factory.makePOTemplate(distroseries=distroseries) |
327 | + dsp = self.factory.makeDSPCache(distroseries=distroseries) |
328 | + form = { |
329 | + 'field.name': potemplate.name, |
330 | + 'field.distroseries': distroseries.name, |
331 | + 'field.sourcepackagename': dsp.sourcepackagename.name, |
332 | + 'field.actions.change': 'Change', |
333 | + } |
334 | + with celebrity_logged_in('rosetta_experts'): |
335 | + view = create_initialized_view(potemplate, '+edit', form=form) |
336 | + self.assertEqual([], view.errors) |
337 | + self.assertEqual( |
338 | + dsp.sourcepackagename.name, potemplate.sourcepackagename.name) |
339 | + |
340 | |
341 | class TestPOTemplateAdminViewValidation(TestPOTemplateEditViewValidation): |
342 | |
343 | @@ -194,3 +232,30 @@ |
344 | self.assertEqual( |
345 | [u'Choose a distribution release series or a project ' |
346 | u'release series, but not both.'], view.errors) |
347 | + |
348 | + def test_change_from_sourcepackage(self): |
349 | + # Changing the source package the template comes from is honoured. |
350 | + distroseries = self.factory.makeDistroSeries() |
351 | + dsp = self.factory.makeDSPCache(distroseries=distroseries) |
352 | + potemplate = self.factory.makePOTemplate( |
353 | + distroseries=distroseries, sourcepackagename=dsp.sourcepackagename) |
354 | + from_dsp = self.factory.makeDSPCache(distroseries=distroseries) |
355 | + form = { |
356 | + 'field.name': potemplate.name, |
357 | + 'field.distroseries': '%s/%s' % ( |
358 | + distroseries.distribution.name, distroseries.name), |
359 | + 'field.sourcepackagename': dsp.sourcepackagename.name, |
360 | + 'field.from_sourcepackagename': from_dsp.sourcepackagename.name, |
361 | + 'field.actions.change': 'Change', |
362 | + } |
363 | + with celebrity_logged_in('rosetta_experts'): |
364 | + view = create_initialized_view(potemplate, '+admin', form=form) |
365 | + self.assertEqual([], view.errors) |
366 | + self.assertEqual( |
367 | + dsp.sourcepackagename.name, potemplate.sourcepackagename.name) |
368 | + self.assertEqual( |
369 | + from_dsp.sourcepackagename.name, |
370 | + potemplate.from_sourcepackagename.name) |
371 | + |
372 | + |
373 | +load_tests = load_tests_apply_scenarios |
374 | |
375 | === added directory 'lib/lp/translations/browser/widgets' |
376 | === added file 'lib/lp/translations/browser/widgets/__init__.py' |
377 | === added file 'lib/lp/translations/browser/widgets/potemplate.py' |
378 | --- lib/lp/translations/browser/widgets/potemplate.py 1970-01-01 00:00:00 +0000 |
379 | +++ lib/lp/translations/browser/widgets/potemplate.py 2016-09-12 15:29:12 +0000 |
380 | @@ -0,0 +1,62 @@ |
381 | +# Copyright 2016 Canonical Ltd. This software is licensed under the |
382 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
383 | + |
384 | +"""Widgets related to `IPOTemplate`.""" |
385 | + |
386 | +from __future__ import absolute_import, print_function, unicode_literals |
387 | + |
388 | +__metaclass__ = type |
389 | +__all__ = [ |
390 | + "POTemplateAdminSourcePackageNameWidget", |
391 | + "POTemplateEditSourcePackageNameWidget", |
392 | + ] |
393 | + |
394 | +from lp.app.errors import UnexpectedFormData |
395 | +from lp.app.widgets.popup import SourcePackageNameWidgetBase |
396 | +from lp.registry.vocabularies import DistroSeriesVocabulary |
397 | + |
398 | + |
399 | +class POTemplateEditSourcePackageNameWidget(SourcePackageNameWidgetBase): |
400 | + """A widget for associating a POTemplate with a SourcePackageName. |
401 | + |
402 | + This is suitable for use on POTemplate:+edit, where the distribution is |
403 | + fixed. |
404 | + """ |
405 | + |
406 | + @property |
407 | + def distribution_name(self): |
408 | + distribution = self.getDistribution() |
409 | + if distribution is not None: |
410 | + return distribution.name |
411 | + else: |
412 | + return '' |
413 | + |
414 | + def getDistribution(self): |
415 | + """See `SourcePackageNameWidgetBase`.""" |
416 | + return self.context.context.distribution |
417 | + |
418 | + |
419 | +class POTemplateAdminSourcePackageNameWidget(SourcePackageNameWidgetBase): |
420 | + """A widget for associating a POTemplate with a SourcePackageName. |
421 | + |
422 | + This is suitable for use on POTemplate:+admin, where the distribution |
423 | + may be changed via the distroseries field. |
424 | + """ |
425 | + |
426 | + @property |
427 | + def distroseries_id(self): |
428 | + return self._prefix + 'distroseries' |
429 | + |
430 | + def getDistribution(self): |
431 | + """See `SourcePackageNameWidgetBase`.""" |
432 | + distroseries_token = self.request.form.get('field.distroseries') |
433 | + if distroseries_token is None: |
434 | + # Fall back to the POTemplate's current distribution. |
435 | + return self.context.context.distribution |
436 | + distroseries_vocab = DistroSeriesVocabulary() |
437 | + try: |
438 | + term = distroseries_vocab.getTermByToken(distroseries_token) |
439 | + except LookupError: |
440 | + raise UnexpectedFormData( |
441 | + "No such distribution series: %s" % distroseries_token) |
442 | + return term.value.distribution |
443 | |
444 | === added directory 'lib/lp/translations/browser/widgets/tests' |
445 | === added file 'lib/lp/translations/browser/widgets/tests/__init__.py' |
446 | === added file 'lib/lp/translations/browser/widgets/tests/test_potemplate.py' |
447 | --- lib/lp/translations/browser/widgets/tests/test_potemplate.py 1970-01-01 00:00:00 +0000 |
448 | +++ lib/lp/translations/browser/widgets/tests/test_potemplate.py 2016-09-12 15:29:12 +0000 |
449 | @@ -0,0 +1,134 @@ |
450 | +# Copyright 2016 Canonical Ltd. This software is licensed under the |
451 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
452 | + |
453 | +"""Test the POTemplate widgets.""" |
454 | + |
455 | +from __future__ import absolute_import, print_function, unicode_literals |
456 | + |
457 | +__metaclass__ = type |
458 | + |
459 | +from testscenarios import ( |
460 | + load_tests_apply_scenarios, |
461 | + WithScenarios, |
462 | + ) |
463 | + |
464 | +from lp.app.errors import UnexpectedFormData |
465 | +from lp.services.features.testing import FeatureFixture |
466 | +from lp.services.webapp.servers import LaunchpadTestRequest |
467 | +from lp.testing import TestCaseWithFactory |
468 | +from lp.testing.layers import DatabaseFunctionalLayer |
469 | +from lp.translations.browser.potemplate import IPOTemplateEditForm |
470 | +from lp.translations.browser.widgets.potemplate import ( |
471 | + POTemplateAdminSourcePackageNameWidget, |
472 | + POTemplateEditSourcePackageNameWidget, |
473 | + ) |
474 | +from lp.translations.interfaces.potemplate import IPOTemplate |
475 | + |
476 | + |
477 | +class TestPOTemplateEditSourcePackageNameWidget( |
478 | + WithScenarios, TestCaseWithFactory): |
479 | + |
480 | + layer = DatabaseFunctionalLayer |
481 | + |
482 | + scenarios = [ |
483 | + ("spn_picker", { |
484 | + "features": {}, |
485 | + "interface": IPOTemplate, |
486 | + }), |
487 | + ("dsp_picker", { |
488 | + "features": {u"disclosure.dsp_picker.enabled": u"on"}, |
489 | + "interface": IPOTemplateEditForm, |
490 | + }), |
491 | + ] |
492 | + |
493 | + def setUp(self): |
494 | + super(TestPOTemplateEditSourcePackageNameWidget, self).setUp() |
495 | + if self.features: |
496 | + self.useFixture(FeatureFixture(self.features)) |
497 | + |
498 | + def makeWidget(self, potemplate, form=None): |
499 | + field = self.interface["sourcepackagename"] |
500 | + bound_field = field.bind(potemplate) |
501 | + request = LaunchpadTestRequest(form=form) |
502 | + return POTemplateEditSourcePackageNameWidget( |
503 | + bound_field, bound_field.vocabulary, request) |
504 | + |
505 | + def test_productseries(self): |
506 | + potemplate = self.factory.makePOTemplate() |
507 | + widget = self.makeWidget(potemplate) |
508 | + self.assertIsNone(widget.getDistribution()) |
509 | + self.assertEqual("", widget.distribution_name) |
510 | + |
511 | + def test_distroseries(self): |
512 | + distroseries = self.factory.makeDistroSeries() |
513 | + potemplate = self.factory.makePOTemplate(distroseries=distroseries) |
514 | + widget = self.makeWidget(potemplate) |
515 | + self.assertEqual(distroseries.distribution, widget.getDistribution()) |
516 | + self.assertEqual( |
517 | + distroseries.distribution.name, widget.distribution_name) |
518 | + |
519 | + |
520 | +class TestPOTemplateAdminSourcePackageNameWidget( |
521 | + WithScenarios, TestCaseWithFactory): |
522 | + |
523 | + layer = DatabaseFunctionalLayer |
524 | + |
525 | + scenarios = [ |
526 | + ("spn_picker", { |
527 | + "features": {}, |
528 | + "interface": IPOTemplate, |
529 | + }), |
530 | + ("dsp_picker", { |
531 | + "features": {u"disclosure.dsp_picker.enabled": u"on"}, |
532 | + "interface": IPOTemplateEditForm, |
533 | + }), |
534 | + ] |
535 | + |
536 | + def setUp(self): |
537 | + super(TestPOTemplateAdminSourcePackageNameWidget, self).setUp() |
538 | + if self.features: |
539 | + self.useFixture(FeatureFixture(self.features)) |
540 | + |
541 | + def makeWidget(self, potemplate, form=None): |
542 | + field = self.interface["sourcepackagename"] |
543 | + bound_field = field.bind(potemplate) |
544 | + request = LaunchpadTestRequest(form=form) |
545 | + return POTemplateAdminSourcePackageNameWidget( |
546 | + bound_field, bound_field.vocabulary, request) |
547 | + |
548 | + def test_distroseries_id(self): |
549 | + potemplate = self.factory.makePOTemplate() |
550 | + distroseries = self.factory.makeDistroSeries() |
551 | + form = { |
552 | + "field.distroseries": "%s/%s" % ( |
553 | + distroseries.distribution.name, distroseries.name), |
554 | + } |
555 | + widget = self.makeWidget(potemplate, form=form) |
556 | + self.assertEqual("field.distroseries", widget.distroseries_id) |
557 | + |
558 | + def test_getDistribution(self): |
559 | + potemplate = self.factory.makePOTemplate() |
560 | + distroseries = self.factory.makeDistroSeries() |
561 | + form = { |
562 | + "field.distroseries": "%s/%s" % ( |
563 | + distroseries.distribution.name, distroseries.name), |
564 | + } |
565 | + widget = self.makeWidget(potemplate, form=form) |
566 | + self.assertEqual(distroseries.distribution, widget.getDistribution()) |
567 | + |
568 | + def test_getDistribution_missing_field(self): |
569 | + distroseries = self.factory.makeDistroSeries() |
570 | + potemplate = self.factory.makePOTemplate(distroseries=distroseries) |
571 | + widget = self.makeWidget(potemplate, form={}) |
572 | + self.assertEqual(distroseries.distribution, widget.getDistribution()) |
573 | + |
574 | + def test_getDistribution_non_existent_distroseries(self): |
575 | + potemplate = self.factory.makePOTemplate() |
576 | + form = {"field.distroseries": "not-a-distribution/not-a-series"} |
577 | + self.assertRaises( |
578 | + UnexpectedFormData, |
579 | + lambda: ( |
580 | + self.makeWidget(potemplate, form=form).getDistribution().name)) |
581 | + |
582 | + |
583 | +load_tests = load_tests_apply_scenarios |