Merge lp:~cjwatson/launchpad/potemplate-dsp-vocab into lp:launchpad

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
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 DistributionSourcePackage picker if the appropriate feature flag is set.

Description of the change

Convert POTemplate:+edit and POTemplate:+admin to use the DistributionSourcePackage picker if the appropriate feature flag is set.

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
=== modified file 'lib/lp/app/widgets/popup.py'
--- lib/lp/app/widgets/popup.py 2016-09-12 15:29:11 +0000
+++ lib/lp/app/widgets/popup.py 2016-09-12 15:29:12 +0000
@@ -305,6 +305,7 @@
305 return self._prefix + 'distribution'305 return self._prefix + 'distribution'
306306
307 distribution_name = ''307 distribution_name = ''
308 distroseries_id = ''
308309
309310
310class SourcePackageNameWidgetBase(DistributionSourcePackagePickerWidget):311class SourcePackageNameWidgetBase(DistributionSourcePackagePickerWidget):
@@ -325,6 +326,13 @@
325 super(SourcePackageNameWidgetBase, self).__init__(326 super(SourcePackageNameWidgetBase, self).__init__(
326 field, vocabulary, request)327 field, vocabulary, request)
327 self.cached_values = {}328 self.cached_values = {}
329 if bool(getFeatureFlag('disclosure.dsp_picker.enabled')):
330 # The distribution may change later when we process form input,
331 # but setting it here makes it easier to construct some views,
332 # particularly edit views where we need to render the context.
333 distribution = self.getDistribution()
334 if distribution is not None:
335 self.context.vocabulary.setDistribution(distribution)
328336
329 def getDistribution(self):337 def getDistribution(self):
330 """Get the distribution used for package validation.338 """Get the distribution used for package validation.
331339
=== modified file 'lib/lp/app/widgets/templates/distributionsourcepackage-picker.pt'
--- lib/lp/app/widgets/templates/distributionsourcepackage-picker.pt 2016-07-21 20:22:00 +0000
+++ lib/lp/app/widgets/templates/distributionsourcepackage-picker.pt 2016-09-12 15:29:12 +0000
@@ -9,6 +9,7 @@
9 var config = ${view/json_config};9 var config = ${view/json_config};
10 var distribution_name = '${view/distribution_name}';10 var distribution_name = '${view/distribution_name}';
11 var distribution_id = '${view/distribution_id}';11 var distribution_id = '${view/distribution_id}';
12 var distroseries_id = '${view/distroseries_id}';
12 if (distribution_name !== '') {13 if (distribution_name !== '') {
13 config.getContextPath = function() {14 config.getContextPath = function() {
14 return '/' + distribution_name;15 return '/' + distribution_name;
@@ -17,6 +18,10 @@
17 config.getContextPath = function() {18 config.getContextPath = function() {
18 return '/' + Y.DOM.byId(distribution_id).value;19 return '/' + Y.DOM.byId(distribution_id).value;
19 };20 };
21 } else if (distroseries_id !== '') {
22 config.getContextPath = function() {
23 return '/' + Y.DOM.byId(distroseries_id).value.split('/', 2)[0];
24 };
20 }25 }
21 var show_widget_id = '${view/show_widget_id}';26 var show_widget_id = '${view/show_widget_id}';
22 Y.on('domready', function(e) {27 Y.on('domready', function(e) {
2328
=== modified file 'lib/lp/bugs/browser/widgets/bugtask.py'
--- lib/lp/bugs/browser/widgets/bugtask.py 2016-09-12 15:29:11 +0000
+++ lib/lp/bugs/browser/widgets/bugtask.py 2016-09-12 15:29:12 +0000
@@ -505,8 +505,7 @@
505 """See `SourcePackageNameWidgetBase`."""505 """See `SourcePackageNameWidgetBase`."""
506 distribution_name = self.request.form.get('field.distribution')506 distribution_name = self.request.form.get('field.distribution')
507 if distribution_name is None:507 if distribution_name is None:
508 raise UnexpectedFormData(508 return None
509 "field.distribution wasn't in the request")
510 distribution = getUtility(IDistributionSet).getByName(509 distribution = getUtility(IDistributionSet).getByName(
511 distribution_name)510 distribution_name)
512 if distribution is None:511 if distribution is None:
513512
=== modified file 'lib/lp/bugs/doc/bugtask-package-widget.txt'
--- lib/lp/bugs/doc/bugtask-package-widget.txt 2016-09-12 15:29:11 +0000
+++ lib/lp/bugs/doc/bugtask-package-widget.txt 2016-09-12 15:29:12 +0000
@@ -118,33 +118,30 @@
118 >>> request = LaunchpadTestRequest(118 >>> request = LaunchpadTestRequest(
119 ... form={'field.distribution': 'debian',119 ... form={'field.distribution': 'debian',
120 ... 'field.sourcepackagename': 'linux-2.6.12'})120 ... 'field.sourcepackagename': 'linux-2.6.12'})
121 >>> widget = BugTaskAlsoAffectsSourcePackageNameWidget(121 >>> BugTaskAlsoAffectsSourcePackageNameWidget(
122 ... package_field, package_field.vocabulary, request)122 ... package_field, package_field.vocabulary,
123 >>> widget.getDistribution().name123 ... request).getDistribution().name
124 u'debian'124 u'debian'
125125
126+distrotask always supplies a valid distribution name. If the widget126+distrotask always supplies a valid distribution name or none at all. If the
127doesn't get a name, or the name isn't the name of a distro,127name isn't the name of a distro, UnexpectedFormData is raised.
128UnexpectedFormData is raised.
129128
130 >>> request = LaunchpadTestRequest(129 >>> request = LaunchpadTestRequest(
131 ... form={'field.distribution': 'non-existing',130 ... form={'field.distribution': 'non-existing',
132 ... 'field.sourcepackagename': 'linux-2.6.12'})131 ... 'field.sourcepackagename': 'linux-2.6.12'})
133 >>> widget = BugTaskAlsoAffectsSourcePackageNameWidget(132 >>> BugTaskAlsoAffectsSourcePackageNameWidget(
134 ... package_field, package_field.vocabulary, request)133 ... package_field, package_field.vocabulary,
135 >>> widget.getDistribution().name134 ... request).getDistribution().name
136 Traceback (most recent call last):135 Traceback (most recent call last):
137 ...136 ...
138 UnexpectedFormData: ...137 UnexpectedFormData: ...
139138
140 >>> request = LaunchpadTestRequest(139A GET request usually won't supply a distribution name at all.
141 ... form={'field.sourcepackagename': 'linux-2.6.12'})140
142 >>> widget = BugTaskAlsoAffectsSourcePackageNameWidget(141 >>> request = LaunchpadTestRequest(form={})
143 ... package_field, package_field.vocabulary, request)142 >>> BugTaskAlsoAffectsSourcePackageNameWidget(
144 >>> widget.getDistribution().name143 ... package_field, package_field.vocabulary,
145 Traceback (most recent call last):144 ... request).getDistribution()
146 ...
147 UnexpectedFormData: ...
148145
149146
150FileBugSourcePackageNameWidget147FileBugSourcePackageNameWidget
151148
=== modified file 'lib/lp/translations/browser/potemplate.py'
--- lib/lp/translations/browser/potemplate.py 2016-06-09 20:13:17 +0000
+++ lib/lp/translations/browser/potemplate.py 2016-09-12 15:29:12 +0000
@@ -1,4 +1,4 @@
1# Copyright 2009-2012 Canonical Ltd. This software is licensed under the1# Copyright 2009-2016 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
3"""Browser code for PO templates."""3"""Browser code for PO templates."""
44
@@ -26,6 +26,7 @@
26import operator26import operator
27import os.path27import os.path
2828
29from lazr.restful.interface import copy_field
29from lazr.restful.utils import smartquote30from lazr.restful.utils import smartquote
30import pytz31import pytz
31from storm.expr import (32from storm.expr import (
@@ -41,6 +42,7 @@
41from lp import _42from lp import _
42from lp.app.browser.launchpadform import (43from lp.app.browser.launchpadform import (
43 action,44 action,
45 custom_widget,
44 LaunchpadEditFormView,46 LaunchpadEditFormView,
45 ReturnToReferrerMixin,47 ReturnToReferrerMixin,
46 )48 )
@@ -51,11 +53,15 @@
51 )53 )
52from lp.app.errors import NotFoundError54from lp.app.errors import NotFoundError
53from lp.app.validators.name import valid_name55from lp.app.validators.name import valid_name
56from lp.registry.interfaces.distributionsourcepackage import (
57 IDistributionSourcePackage,
58 )
54from lp.registry.interfaces.role import IPersonRoles59from lp.registry.interfaces.role import IPersonRoles
55from lp.registry.model.packaging import Packaging60from lp.registry.model.packaging import Packaging
56from lp.registry.model.product import Product61from lp.registry.model.product import Product
57from lp.registry.model.productseries import ProductSeries62from lp.registry.model.productseries import ProductSeries
58from lp.registry.model.sourcepackagename import SourcePackageName63from lp.registry.model.sourcepackagename import SourcePackageName
64from lp.services.features import getFeatureFlag
59from lp.services.helpers import is_tar_filename65from lp.services.helpers import is_tar_filename
60from lp.services.propertycache import cachedproperty66from lp.services.propertycache import cachedproperty
61from lp.services.webapp import (67from lp.services.webapp import (
@@ -86,6 +92,10 @@
86from lp.translations.browser.translationsharing import (92from lp.translations.browser.translationsharing import (
87 TranslationSharingDetailsMixin,93 TranslationSharingDetailsMixin,
88 )94 )
95from lp.translations.browser.widgets.potemplate import (
96 POTemplateAdminSourcePackageNameWidget,
97 POTemplateEditSourcePackageNameWidget,
98 )
89from lp.translations.interfaces.pofile import IPOFileSet99from lp.translations.interfaces.pofile import IPOFileSet
90from lp.translations.interfaces.potemplate import (100from lp.translations.interfaces.potemplate import (
91 IPOTemplate,101 IPOTemplate,
@@ -492,10 +502,29 @@
492 return POTemplateView.pofiles(self, preferred_only=True)502 return POTemplateView.pofiles(self, preferred_only=True)
493503
494504
505class IPOTemplateEditForm(IPOTemplate):
506
507 sourcepackagename = copy_field(
508 IPOTemplate['sourcepackagename'],
509 vocabularyName='DistributionSourcePackage')
510
511 from_sourcepackagename = copy_field(
512 IPOTemplate['from_sourcepackagename'],
513 vocabularyName='DistributionSourcePackage')
514
515
495class POTemplateEditView(ReturnToReferrerMixin, LaunchpadEditFormView):516class POTemplateEditView(ReturnToReferrerMixin, LaunchpadEditFormView):
496 """View class that lets you edit a POTemplate object."""517 """View class that lets you edit a POTemplate object."""
497518
498 schema = IPOTemplate519 @property
520 def schema(self):
521 """See `LaunchpadFormView`."""
522 if bool(getFeatureFlag('disclosure.dsp_picker.enabled')):
523 return IPOTemplateEditForm
524 else:
525 return IPOTemplate
526
527 custom_widget('sourcepackagename', POTemplateEditSourcePackageNameWidget)
499 label = 'Edit translation template details'528 label = 'Edit translation template details'
500 page_title = 'Edit details'529 page_title = 'Edit details'
501 PRIORITY_MIN_VALUE = 0530 PRIORITY_MIN_VALUE = 0
@@ -516,6 +545,14 @@
516 return field_names545 return field_names
517546
518 @property547 @property
548 def adapters(self):
549 """See `LaunchpadFormView`."""
550 if bool(getFeatureFlag('disclosure.dsp_picker.enabled')):
551 return {IPOTemplateEditForm: self.context}
552 else:
553 return {}
554
555 @property
519 def _return_url(self):556 def _return_url(self):
520 # We override the ReturnToReferrerMixin _return_url because it might557 # We override the ReturnToReferrerMixin _return_url because it might
521 # change when any of the productseries, distroseries,558 # change when any of the productseries, distroseries,
@@ -548,6 +585,9 @@
548 context.setActive(iscurrent)585 context.setActive(iscurrent)
549 old_description = context.description586 old_description = context.description
550 old_translation_domain = context.translation_domain587 old_translation_domain = context.translation_domain
588 for field in ('sourcepackagename', 'from_sourcepackagename'):
589 if IDistributionSourcePackage.providedBy(data.get(field)):
590 data[field] = data[field].sourcepackagename
551 self.updateContextFromData(data)591 self.updateContextFromData(data)
552 if old_description != context.description:592 if old_description != context.description:
553 self.user.assignKarma(593 self.user.assignKarma(
@@ -565,6 +605,8 @@
565 """Return a POTemplateSubset corresponding to the chosen target."""605 """Return a POTemplateSubset corresponding to the chosen target."""
566 sourcepackagename = data.get('sourcepackagename',606 sourcepackagename = data.get('sourcepackagename',
567 self.context.sourcepackagename)607 self.context.sourcepackagename)
608 if IDistributionSourcePackage.providedBy(sourcepackagename):
609 sourcepackagename = sourcepackagename.sourcepackagename
568 return getUtility(IPOTemplateSet).getSubset(610 return getUtility(IPOTemplateSet).getSubset(
569 distroseries=self.context.distroseries,611 distroseries=self.context.distroseries,
570 sourcepackagename=sourcepackagename,612 sourcepackagename=sourcepackagename,
@@ -582,6 +624,8 @@
582 distroseries = data.get('distroseries', self.context.distroseries)624 distroseries = data.get('distroseries', self.context.distroseries)
583 sourcepackagename = data.get(625 sourcepackagename = data.get(
584 'sourcepackagename', self.context.sourcepackagename)626 'sourcepackagename', self.context.sourcepackagename)
627 if IDistributionSourcePackage.providedBy(sourcepackagename):
628 sourcepackagename = sourcepackagename.sourcepackagename
585 productseries = data.get('productseries', None)629 productseries = data.get('productseries', None)
586 sourcepackage_changed = (630 sourcepackage_changed = (
587 distroseries is not None and631 distroseries is not None and
@@ -656,6 +700,9 @@
656 'from_sourcepackagename', 'sourcepackageversion',700 'from_sourcepackagename', 'sourcepackageversion',
657 'languagepack', 'path', 'source_file_format', 'priority',701 'languagepack', 'path', 'source_file_format', 'priority',
658 'date_last_updated']702 'date_last_updated']
703 custom_widget('sourcepackagename', POTemplateAdminSourcePackageNameWidget)
704 custom_widget(
705 'from_sourcepackagename', POTemplateAdminSourcePackageNameWidget)
659 label = 'Administer translation template'706 label = 'Administer translation template'
660 page_title = "Administer"707 page_title = "Administer"
661708
@@ -663,6 +710,8 @@
663 """Return a POTemplateSubset corresponding to the chosen target."""710 """Return a POTemplateSubset corresponding to the chosen target."""
664 distroseries = data.get('distroseries')711 distroseries = data.get('distroseries')
665 sourcepackagename = data.get('sourcepackagename')712 sourcepackagename = data.get('sourcepackagename')
713 if IDistributionSourcePackage.providedBy(sourcepackagename):
714 sourcepackagename = sourcepackagename.sourcepackagename
666 productseries = data.get('productseries')715 productseries = data.get('productseries')
667716
668 if distroseries is not None and productseries is not None:717 if distroseries is not None and productseries is not None:
669718
=== modified file 'lib/lp/translations/browser/tests/test_potemplate_views.py'
--- lib/lp/translations/browser/tests/test_potemplate_views.py 2012-12-10 13:43:47 +0000
+++ lib/lp/translations/browser/tests/test_potemplate_views.py 2016-09-12 15:29:12 +0000
@@ -1,25 +1,46 @@
1# Copyright 2011 Canonical Ltd. This software is licensed under the1# Copyright 2011-2016 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4"""Module doc."""4"""Module doc."""
55
6__metaclass__ = type6__metaclass__ = type
77
8from testscenarios import (
9 load_tests_apply_scenarios,
10 WithScenarios,
11 )
812
13from lp.services.features.testing import FeatureFixture
9from lp.services.webapp.escaping import html_escape14from lp.services.webapp.escaping import html_escape
10from lp.services.webapp.servers import LaunchpadTestRequest15from lp.services.webapp.servers import LaunchpadTestRequest
11from lp.testing import TestCaseWithFactory16from lp.testing import (
17 celebrity_logged_in,
18 TestCaseWithFactory,
19 )
12from lp.testing.layers import DatabaseFunctionalLayer20from lp.testing.layers import DatabaseFunctionalLayer
21from lp.testing.views import create_initialized_view
13from lp.translations.browser.potemplate import (22from lp.translations.browser.potemplate import (
14 POTemplateAdminView,23 POTemplateAdminView,
15 POTemplateEditView,24 POTemplateEditView,
16 )25 )
1726
1827
19class TestPOTemplateEditViewValidation(TestCaseWithFactory):28class TestPOTemplateEditViewValidation(WithScenarios, TestCaseWithFactory):
2029
21 layer = DatabaseFunctionalLayer30 layer = DatabaseFunctionalLayer
2231
32 scenarios = [
33 ("spn_picker", {"features": {}}),
34 ("dsp_picker", {
35 "features": {u"disclosure.dsp_picker.enabled": u"on"},
36 }),
37 ]
38
39 def setUp(self):
40 super(TestPOTemplateEditViewValidation, self).setUp()
41 if self.features:
42 self.useFixture(FeatureFixture(self.features))
43
23 def _makeData(self, potemplate, **kwargs):44 def _makeData(self, potemplate, **kwargs):
24 """Create form data for the given template with some changed values.45 """Create form data for the given template with some changed values.
2546
@@ -131,6 +152,23 @@
131 [u'Source package already has a template with that same domain.'],152 [u'Source package already has a template with that same domain.'],
132 view.errors)153 view.errors)
133154
155 def test_change_sourcepackage(self):
156 # Changing the source package is honoured.
157 distroseries = self.factory.makeDistroSeries()
158 potemplate = self.factory.makePOTemplate(distroseries=distroseries)
159 dsp = self.factory.makeDSPCache(distroseries=distroseries)
160 form = {
161 'field.name': potemplate.name,
162 'field.distroseries': distroseries.name,
163 'field.sourcepackagename': dsp.sourcepackagename.name,
164 'field.actions.change': 'Change',
165 }
166 with celebrity_logged_in('rosetta_experts'):
167 view = create_initialized_view(potemplate, '+edit', form=form)
168 self.assertEqual([], view.errors)
169 self.assertEqual(
170 dsp.sourcepackagename.name, potemplate.sourcepackagename.name)
171
134172
135class TestPOTemplateAdminViewValidation(TestPOTemplateEditViewValidation):173class TestPOTemplateAdminViewValidation(TestPOTemplateEditViewValidation):
136174
@@ -194,3 +232,30 @@
194 self.assertEqual(232 self.assertEqual(
195 [u'Choose a distribution release series or a project '233 [u'Choose a distribution release series or a project '
196 u'release series, but not both.'], view.errors)234 u'release series, but not both.'], view.errors)
235
236 def test_change_from_sourcepackage(self):
237 # Changing the source package the template comes from is honoured.
238 distroseries = self.factory.makeDistroSeries()
239 dsp = self.factory.makeDSPCache(distroseries=distroseries)
240 potemplate = self.factory.makePOTemplate(
241 distroseries=distroseries, sourcepackagename=dsp.sourcepackagename)
242 from_dsp = self.factory.makeDSPCache(distroseries=distroseries)
243 form = {
244 'field.name': potemplate.name,
245 'field.distroseries': '%s/%s' % (
246 distroseries.distribution.name, distroseries.name),
247 'field.sourcepackagename': dsp.sourcepackagename.name,
248 'field.from_sourcepackagename': from_dsp.sourcepackagename.name,
249 'field.actions.change': 'Change',
250 }
251 with celebrity_logged_in('rosetta_experts'):
252 view = create_initialized_view(potemplate, '+admin', form=form)
253 self.assertEqual([], view.errors)
254 self.assertEqual(
255 dsp.sourcepackagename.name, potemplate.sourcepackagename.name)
256 self.assertEqual(
257 from_dsp.sourcepackagename.name,
258 potemplate.from_sourcepackagename.name)
259
260
261load_tests = load_tests_apply_scenarios
197262
=== added directory 'lib/lp/translations/browser/widgets'
=== added file 'lib/lp/translations/browser/widgets/__init__.py'
=== added file 'lib/lp/translations/browser/widgets/potemplate.py'
--- lib/lp/translations/browser/widgets/potemplate.py 1970-01-01 00:00:00 +0000
+++ lib/lp/translations/browser/widgets/potemplate.py 2016-09-12 15:29:12 +0000
@@ -0,0 +1,62 @@
1# Copyright 2016 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4"""Widgets related to `IPOTemplate`."""
5
6from __future__ import absolute_import, print_function, unicode_literals
7
8__metaclass__ = type
9__all__ = [
10 "POTemplateAdminSourcePackageNameWidget",
11 "POTemplateEditSourcePackageNameWidget",
12 ]
13
14from lp.app.errors import UnexpectedFormData
15from lp.app.widgets.popup import SourcePackageNameWidgetBase
16from lp.registry.vocabularies import DistroSeriesVocabulary
17
18
19class POTemplateEditSourcePackageNameWidget(SourcePackageNameWidgetBase):
20 """A widget for associating a POTemplate with a SourcePackageName.
21
22 This is suitable for use on POTemplate:+edit, where the distribution is
23 fixed.
24 """
25
26 @property
27 def distribution_name(self):
28 distribution = self.getDistribution()
29 if distribution is not None:
30 return distribution.name
31 else:
32 return ''
33
34 def getDistribution(self):
35 """See `SourcePackageNameWidgetBase`."""
36 return self.context.context.distribution
37
38
39class POTemplateAdminSourcePackageNameWidget(SourcePackageNameWidgetBase):
40 """A widget for associating a POTemplate with a SourcePackageName.
41
42 This is suitable for use on POTemplate:+admin, where the distribution
43 may be changed via the distroseries field.
44 """
45
46 @property
47 def distroseries_id(self):
48 return self._prefix + 'distroseries'
49
50 def getDistribution(self):
51 """See `SourcePackageNameWidgetBase`."""
52 distroseries_token = self.request.form.get('field.distroseries')
53 if distroseries_token is None:
54 # Fall back to the POTemplate's current distribution.
55 return self.context.context.distribution
56 distroseries_vocab = DistroSeriesVocabulary()
57 try:
58 term = distroseries_vocab.getTermByToken(distroseries_token)
59 except LookupError:
60 raise UnexpectedFormData(
61 "No such distribution series: %s" % distroseries_token)
62 return term.value.distribution
063
=== added directory 'lib/lp/translations/browser/widgets/tests'
=== added file 'lib/lp/translations/browser/widgets/tests/__init__.py'
=== added file 'lib/lp/translations/browser/widgets/tests/test_potemplate.py'
--- lib/lp/translations/browser/widgets/tests/test_potemplate.py 1970-01-01 00:00:00 +0000
+++ lib/lp/translations/browser/widgets/tests/test_potemplate.py 2016-09-12 15:29:12 +0000
@@ -0,0 +1,134 @@
1# Copyright 2016 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4"""Test the POTemplate widgets."""
5
6from __future__ import absolute_import, print_function, unicode_literals
7
8__metaclass__ = type
9
10from testscenarios import (
11 load_tests_apply_scenarios,
12 WithScenarios,
13 )
14
15from lp.app.errors import UnexpectedFormData
16from lp.services.features.testing import FeatureFixture
17from lp.services.webapp.servers import LaunchpadTestRequest
18from lp.testing import TestCaseWithFactory
19from lp.testing.layers import DatabaseFunctionalLayer
20from lp.translations.browser.potemplate import IPOTemplateEditForm
21from lp.translations.browser.widgets.potemplate import (
22 POTemplateAdminSourcePackageNameWidget,
23 POTemplateEditSourcePackageNameWidget,
24 )
25from lp.translations.interfaces.potemplate import IPOTemplate
26
27
28class TestPOTemplateEditSourcePackageNameWidget(
29 WithScenarios, TestCaseWithFactory):
30
31 layer = DatabaseFunctionalLayer
32
33 scenarios = [
34 ("spn_picker", {
35 "features": {},
36 "interface": IPOTemplate,
37 }),
38 ("dsp_picker", {
39 "features": {u"disclosure.dsp_picker.enabled": u"on"},
40 "interface": IPOTemplateEditForm,
41 }),
42 ]
43
44 def setUp(self):
45 super(TestPOTemplateEditSourcePackageNameWidget, self).setUp()
46 if self.features:
47 self.useFixture(FeatureFixture(self.features))
48
49 def makeWidget(self, potemplate, form=None):
50 field = self.interface["sourcepackagename"]
51 bound_field = field.bind(potemplate)
52 request = LaunchpadTestRequest(form=form)
53 return POTemplateEditSourcePackageNameWidget(
54 bound_field, bound_field.vocabulary, request)
55
56 def test_productseries(self):
57 potemplate = self.factory.makePOTemplate()
58 widget = self.makeWidget(potemplate)
59 self.assertIsNone(widget.getDistribution())
60 self.assertEqual("", widget.distribution_name)
61
62 def test_distroseries(self):
63 distroseries = self.factory.makeDistroSeries()
64 potemplate = self.factory.makePOTemplate(distroseries=distroseries)
65 widget = self.makeWidget(potemplate)
66 self.assertEqual(distroseries.distribution, widget.getDistribution())
67 self.assertEqual(
68 distroseries.distribution.name, widget.distribution_name)
69
70
71class TestPOTemplateAdminSourcePackageNameWidget(
72 WithScenarios, TestCaseWithFactory):
73
74 layer = DatabaseFunctionalLayer
75
76 scenarios = [
77 ("spn_picker", {
78 "features": {},
79 "interface": IPOTemplate,
80 }),
81 ("dsp_picker", {
82 "features": {u"disclosure.dsp_picker.enabled": u"on"},
83 "interface": IPOTemplateEditForm,
84 }),
85 ]
86
87 def setUp(self):
88 super(TestPOTemplateAdminSourcePackageNameWidget, self).setUp()
89 if self.features:
90 self.useFixture(FeatureFixture(self.features))
91
92 def makeWidget(self, potemplate, form=None):
93 field = self.interface["sourcepackagename"]
94 bound_field = field.bind(potemplate)
95 request = LaunchpadTestRequest(form=form)
96 return POTemplateAdminSourcePackageNameWidget(
97 bound_field, bound_field.vocabulary, request)
98
99 def test_distroseries_id(self):
100 potemplate = self.factory.makePOTemplate()
101 distroseries = self.factory.makeDistroSeries()
102 form = {
103 "field.distroseries": "%s/%s" % (
104 distroseries.distribution.name, distroseries.name),
105 }
106 widget = self.makeWidget(potemplate, form=form)
107 self.assertEqual("field.distroseries", widget.distroseries_id)
108
109 def test_getDistribution(self):
110 potemplate = self.factory.makePOTemplate()
111 distroseries = self.factory.makeDistroSeries()
112 form = {
113 "field.distroseries": "%s/%s" % (
114 distroseries.distribution.name, distroseries.name),
115 }
116 widget = self.makeWidget(potemplate, form=form)
117 self.assertEqual(distroseries.distribution, widget.getDistribution())
118
119 def test_getDistribution_missing_field(self):
120 distroseries = self.factory.makeDistroSeries()
121 potemplate = self.factory.makePOTemplate(distroseries=distroseries)
122 widget = self.makeWidget(potemplate, form={})
123 self.assertEqual(distroseries.distribution, widget.getDistribution())
124
125 def test_getDistribution_non_existent_distroseries(self):
126 potemplate = self.factory.makePOTemplate()
127 form = {"field.distroseries": "not-a-distribution/not-a-series"}
128 self.assertRaises(
129 UnexpectedFormData,
130 lambda: (
131 self.makeWidget(potemplate, form=form).getDistribution().name))
132
133
134load_tests = load_tests_apply_scenarios