launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #31724
[Merge] ~alvarocs/launchpad:update-ibugtarget-for-template into launchpad:master
Alvaro Crespo Serrano has proposed merging ~alvarocs/launchpad:update-ibugtarget-for-template into launchpad:master.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~alvarocs/launchpad/+git/launchpad/+merge/475346
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~alvarocs/launchpad:update-ibugtarget-for-template into launchpad:master.
diff --git a/database/schema/patch-2211-30-0.sql b/database/schema/patch-2211-30-0.sql
new file mode 100644
index 0000000..d998031
--- /dev/null
+++ b/database/schema/patch-2211-30-0.sql
@@ -0,0 +1,18 @@
+-- Copyright 2024 Canonical Ltd. This software is licensed under the
+-- GNU Affero General Public License version 3 (see the file LICENSE).
+
+SET client_min_messages=ERROR;
+
+ALTER TABLE distribution ADD COLUMN lp_templates JSONB;
+ALTER TABLE distributionsourcepackage ADD COLUMN lp_templates JSONB;
+ALTER TABLE product ADD COLUMN lp_templates JSONB;
+ALTER TABLE ociproject ADD COLUMN lp_templates JSONB;
+ALTER TABLE project ADD COLUMN lp_templates JSONB;
+
+COMMENT ON COLUMN distribution.lp_templates IS 'A JSON data structure that contains different templates for Launchpad';
+COMMENT ON COLUMN distributionsourcepackage.lp_templates IS 'A JSON data structure that contains different templates for Launchpad';
+COMMENT ON COLUMN product.lp_templates IS 'A JSON data structure that contains different templates for Launchpad';
+COMMENT ON COLUMN ociproject.lp_templates IS 'A JSON data structure that contains different templates for Launchpad';
+COMMENT ON COLUMN project.lp_templates IS 'A JSON data structure that contains different templates for Launchpad';
+
+INSERT INTO LaunchpadDatabaseRevision VALUES (2211, 30, 0);
diff --git a/lib/lp/bugs/browser/bugtarget.py b/lib/lp/bugs/browser/bugtarget.py
index cd5b919..e738682 100644
--- a/lib/lp/bugs/browser/bugtarget.py
+++ b/lib/lp/bugs/browser/bugtarget.py
@@ -72,7 +72,11 @@ from lp.app.widgets.product import (
from lp.bugs.browser.structuralsubscription import (
expose_structural_subscription_data_to_js,
)
-from lp.bugs.browser.widgets.bug import BugTagsWidget, LargeBugTagsWidget
+from lp.bugs.browser.widgets.bug import (
+ BugTagsWidget,
+ DictBugTemplatesWidget,
+ LargeBugTagsWidget,
+)
from lp.bugs.browser.widgets.bugtask import FileBugSourcePackageNameWidget
from lp.bugs.interfaces.apportjob import IProcessApportBlobJobSource
from lp.bugs.interfaces.bug import (
@@ -143,6 +147,7 @@ class IProductBugConfiguration(Interface):
bug_reporting_guidelines = copy_field(
IBugTarget["bug_reporting_guidelines"]
)
+ lp_templates = copy_field(IBugTarget["lp_templates"])
bug_reported_acknowledgement = copy_field(
IBugTarget["bug_reported_acknowledgement"]
)
@@ -167,6 +172,7 @@ class ProductConfigureBugTrackerView(ProductConfigureBase):
custom_widget_bugtracker = ProductBugTrackerWidget
custom_widget_enable_bug_expiration = GhostCheckBoxWidget
custom_widget_remote_product = GhostWidget
+ custom_widget_bug_templates = CustomWidgetFactory(DictBugTemplatesWidget)
@property
def field_names(self):
@@ -176,6 +182,7 @@ class ProductConfigureBugTrackerView(ProductConfigureBase):
"enable_bug_expiration",
"remote_product",
"bug_reporting_guidelines",
+ "lp_templates",
"bug_reported_acknowledgement",
"enable_bugfiling_duplicate_search",
]
@@ -211,6 +218,8 @@ class FileBugViewBase(LaunchpadFormView):
TextAreaWidget, cssClass="comment-text"
)
custom_widget_packagename = FileBugSourcePackageNameWidget
+ custom_widget_bug_templates = CustomWidgetFactory(DictBugTemplatesWidget)
+
next_url = None
extra_data_token = None
@@ -292,6 +301,11 @@ class FileBugViewBase(LaunchpadFormView):
"Extra debug information will be added to the bug report"
" automatically."
)
+ # Update Comment field with a bug reporting template if it exists
+ lp_templates = self.context.lp_templates
+ if lp_templates and "bug_templates" in lp_templates:
+ template_text = lp_templates["bug_templates"]["default"]
+ self.widgets["comment"].setRenderedValue(template_text)
@cachedproperty
def redirect_ubuntu_filebug(self):
@@ -898,6 +912,13 @@ class FileBugViewBase(LaunchpadFormView):
return self.getAcknowledgementMessage(next_context)
return self.default_bug_reported_acknowledgement
+ def getBugTemplate(self, context):
+ """Default bug template configured that is displayed to the user."""
+ bug_template = context.lp_templates["bug_templates"]["default"]
+ if bug_template is not None and len(bug_template.strip()) > 0:
+ return bug_template
+ return ""
+
@cachedproperty
def extra_data_processing_job(self):
"""Return the ProcessApportBlobJob for a given BLOB token."""
diff --git a/lib/lp/bugs/browser/tests/test_bugtarget_configure.py b/lib/lp/bugs/browser/tests/test_bugtarget_configure.py
index 77d3dad..0840385 100644
--- a/lib/lp/bugs/browser/tests/test_bugtarget_configure.py
+++ b/lib/lp/bugs/browser/tests/test_bugtarget_configure.py
@@ -31,6 +31,7 @@ class TestProductBugConfigurationView(TestCaseWithFactory):
"field.enable_bug_expiration": "on",
"field.remote_product": "sf-boing",
"field.bug_reporting_guidelines": "guidelines",
+ "field.lp_templates": "launchpad templates",
"field.bug_reported_acknowledgement": "acknowledgement message",
"field.enable_bugfiling_duplicate_search": False,
"field.actions.change": "Change",
@@ -47,6 +48,7 @@ class TestProductBugConfigurationView(TestCaseWithFactory):
"enable_bug_expiration",
"remote_product",
"bug_reporting_guidelines",
+ "lp_templates",
"bug_reported_acknowledgement",
"enable_bugfiling_duplicate_search",
"bug_supervisor",
@@ -67,6 +69,7 @@ class TestProductBugConfigurationView(TestCaseWithFactory):
"enable_bug_expiration",
"remote_product",
"bug_reporting_guidelines",
+ "lp_templates",
"bug_reported_acknowledgement",
"enable_bugfiling_duplicate_search",
]
@@ -91,6 +94,10 @@ class TestProductBugConfigurationView(TestCaseWithFactory):
self.assertEqual("sf-boing", self.product.remote_product)
self.assertEqual("guidelines", self.product.bug_reporting_guidelines)
self.assertEqual(
+ {"bug_templates": {"default": "launchpad templates"}},
+ self.product.lp_templates,
+ )
+ self.assertEqual(
"acknowledgement message",
self.product.bug_reported_acknowledgement,
)
@@ -150,9 +157,10 @@ class TestProductBugConfigurationView(TestCaseWithFactory):
self.product.bug_supervisor = bug_team
login_person(weak_owner)
form = self._makeForm()
- # Only the bug_reporting_guidelines are different.
+ # Only the bug_reporting_guidelines and lp_templates are different.
form["field.bug_supervisor"] = bug_team.name
form["field.bug_reporting_guidelines"] = "new guidelines"
+ form["field.lp_templates"] = "new lp template"
view = create_initialized_view(
self.product, name="+configure-bugtracker", form=form
)
@@ -160,12 +168,17 @@ class TestProductBugConfigurationView(TestCaseWithFactory):
self.assertEqual(
"new guidelines", self.product.bug_reporting_guidelines
)
+ self.assertEqual(
+ {"bug_templates": {"default": "new lp template"}},
+ self.product.lp_templates,
+ )
def test_bug_supervisor_can_edit(self):
login_person(self.bug_supervisor)
form = self._makeForm()
- # Only the bug_reporting_guidelines are different.
+ # Only the bug_reporting_guidelines and lp_templates are different.
form["field.bug_reporting_guidelines"] = "new guidelines"
+ form["field.lp_templates"] = "new lp template"
view = create_initialized_view(
self.product, name="+configure-bugtracker", form=form
)
@@ -173,3 +186,7 @@ class TestProductBugConfigurationView(TestCaseWithFactory):
self.assertEqual(
"new guidelines", self.product.bug_reporting_guidelines
)
+ self.assertEqual(
+ {"bug_templates": {"default": "new lp template"}},
+ self.product.lp_templates,
+ )
diff --git a/lib/lp/bugs/browser/tests/test_bugtarget_filebug.py b/lib/lp/bugs/browser/tests/test_bugtarget_filebug.py
index 0e1450d..15e84c9 100644
--- a/lib/lp/bugs/browser/tests/test_bugtarget_filebug.py
+++ b/lib/lp/bugs/browser/tests/test_bugtarget_filebug.py
@@ -387,6 +387,19 @@ class TestFileBugViewBase(FileBugViewMixin, TestCaseWithFactory):
]
self.assertEqual(expected_guidelines, view.bug_reporting_guidelines)
+ def test_filebug_template_in_comment(self):
+ # Create a product
+ product = self.factory.makeProduct()
+ login_person(product.owner)
+ # Set up lp_templates
+ product.lp_templates = {
+ "bug_templates": {"default": "This is a default bug template"}
+ }
+ # Create and initialize the product filebug view
+ view = create_initialized_view(product, "+filebug")
+ expected_template = "This is a default bug template"
+ self.assertEqual(expected_template, view.getBugTemplate(product))
+
def filebug_via_view(
self,
information_type=None,
diff --git a/lib/lp/bugs/browser/widgets/bug.py b/lib/lp/bugs/browser/widgets/bug.py
index 5c327b1..a5bec56 100644
--- a/lib/lp/bugs/browser/widgets/bug.py
+++ b/lib/lp/bugs/browser/widgets/bug.py
@@ -6,14 +6,20 @@ __all__ = [
"BugTagsWidget",
"BugWidget",
"LargeBugTagsWidget",
+ "DictBugTemplatesWidget",
]
import json
import re
from zope.component import getUtility
-from zope.formlib.interfaces import ConversionError, WidgetInputError
+from zope.formlib.interfaces import (
+ ConversionError,
+ IInputWidget,
+ WidgetInputError,
+)
from zope.formlib.textwidgets import IntWidget, TextAreaWidget, TextWidget
+from zope.interface import implementer
from zope.schema.interfaces import ConstraintNotSatisfied
from lp.app.errors import NotFoundError
@@ -201,3 +207,30 @@ class LargeBugTagsWidget(BugTagsWidgetBase, TextAreaWidget):
def _getInputValue(self):
return TextAreaWidget.getInputValue(self)
+
+
+@implementer(IInputWidget)
+class DictBugTemplatesWidget(TextAreaWidget):
+ """Widget for editing bug templates as JSON or plain text."""
+
+ def _toFieldValue(self, input):
+ """Convert the input text to a dictionary for the schema."""
+ if not input:
+ return {"bug_templates": {"default": ""}}
+
+ # Perform length validation
+ if len(input) > 50000:
+ raise ConversionError(
+ "The bug template is too long. If you have lots of text to "
+ "add, ask to attach a file to the bug instead."
+ )
+
+ # Add text input as default bug template
+ return {"bug_templates": {"default": input.strip()}}
+
+ def _toFormValue(self, value):
+ """Convert a dictionary from the schema back to string for the form."""
+ if not value:
+ return ""
+ # Return the default bug template
+ return value["bug_templates"]["default"]
diff --git a/lib/lp/bugs/browser/widgets/configure.zcml b/lib/lp/bugs/browser/widgets/configure.zcml
index d8f311e..036adc3 100644
--- a/lib/lp/bugs/browser/widgets/configure.zcml
+++ b/lib/lp/bugs/browser/widgets/configure.zcml
@@ -16,4 +16,10 @@
permission="zope.Public"
/>
+ <!-- Adapter for DictBugTemplatesWidget -->
+ <adapter
+ factory="lp.bugs.browser.widgets.bug.DictBugTemplatesWidget"
+ for="zope.schema.interfaces.IDict zope.publisher.interfaces.browser.IBrowserRequest"
+ provides="zope.formlib.interfaces.IInputWidget"
+ />
</configure>
diff --git a/lib/lp/bugs/browser/widgets/tests/test_bug.py b/lib/lp/bugs/browser/widgets/tests/test_bug.py
index cc7f2a4..b5144e0 100644
--- a/lib/lp/bugs/browser/widgets/tests/test_bug.py
+++ b/lib/lp/bugs/browser/widgets/tests/test_bug.py
@@ -1,7 +1,10 @@
# Copyright 2012 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
-from lp.bugs.browser.widgets.bug import BugTagsWidget
+from zope.formlib.interfaces import ConversionError
+from zope.schema import Text
+
+from lp.bugs.browser.widgets.bug import BugTagsWidget, DictBugTemplatesWidget
from lp.bugs.interfaces.bugtarget import IHasOfficialBugTags
from lp.services.webapp.servers import LaunchpadTestRequest
from lp.testing import TestCaseWithFactory, person_logged_in
@@ -74,3 +77,51 @@ class BugTagsWidgetTestCase(TestCaseWithFactory):
"""'input[id="field.official_bug_tags"][type="text"]',""", markup
)
self.assertIn("official_tags)", markup)
+
+
+class DictBugTemplatesWidgetTestCase(TestCaseWithFactory):
+ layer = DatabaseFunctionalLayer
+
+ def test_toFieldValue_empty_input(self):
+ """Test _toFieldValue when the input is empty."""
+ field = Text(__name__="test_lp_bug_template")
+ widget = DictBugTemplatesWidget(field, LaunchpadTestRequest())
+ result = widget._toFieldValue("")
+ self.assertEqual(result, {"bug_templates": {"default": ""}})
+
+ def test_toFieldValue_with_input(self):
+ """Test _toFieldValue when the input has a bug template."""
+ field = Text(__name__="test_lp_bug_template")
+ widget = DictBugTemplatesWidget(field, LaunchpadTestRequest())
+ result = widget._toFieldValue("template content")
+ self.assertEqual(
+ result, {"bug_templates": {"default": "template content"}}
+ )
+
+ def test_toFieldValue_with_too_large_input(self):
+ """Test _toFieldValue when the input is larger than threshold."""
+ field = Text(__name__="test_lp_bug_template")
+ widget = DictBugTemplatesWidget(field, LaunchpadTestRequest())
+ self.assertRaisesRegex(
+ ConversionError,
+ "The bug template is too long. If you have lots of text to "
+ "add, ask to attach a file to the bug instead.",
+ widget._toFieldValue,
+ "x" * 50001,
+ )
+
+ def test_toFormValue_empty_input(self):
+ """Test _toFormValue when the value is an empty dict."""
+ field = Text(__name__="test_lp_bug_template")
+ widget = DictBugTemplatesWidget(field, LaunchpadTestRequest())
+ result = widget._toFormValue({})
+ self.assertEqual(result, "")
+
+ def test_toFormValue_with_input(self):
+ """Test _toFormValue when the value has a bug template."""
+ field = Text(__name__="test_lp_bug_template")
+ widget = DictBugTemplatesWidget(field, LaunchpadTestRequest())
+ result = widget._toFormValue(
+ {"bug_templates": {"default": "template content"}}
+ )
+ self.assertEqual(result, "template content")
diff --git a/lib/lp/bugs/interfaces/bug.py b/lib/lp/bugs/interfaces/bug.py
index acf5c6e..0f31c6a 100644
--- a/lib/lp/bugs/interfaces/bug.py
+++ b/lib/lp/bugs/interfaces/bug.py
@@ -1450,7 +1450,7 @@ class IBugAddForm(IBug):
)
owner = Int(title=_("Owner"), required=True)
comment = Description(
- title=_("Further information"),
+ title=_("Bug Description"),
strip_text=True,
trailing_only=True,
min_length=1,
diff --git a/lib/lp/bugs/interfaces/bugtarget.py b/lib/lp/bugs/interfaces/bugtarget.py
index 3a090e6..ffb9909 100644
--- a/lib/lp/bugs/interfaces/bugtarget.py
+++ b/lib/lp/bugs/interfaces/bugtarget.py
@@ -34,7 +34,16 @@ from lazr.restful.declarations import (
from lazr.restful.fields import Reference
from lazr.restful.interface import copy_field
from zope.interface import Attribute, Interface
-from zope.schema import Bool, Choice, Datetime, List, Object, Text
+from zope.schema import (
+ Bool,
+ Choice,
+ Datetime,
+ Dict,
+ List,
+ Object,
+ Text,
+ TextLine,
+)
from lp import _
from lp.app.enums import (
@@ -267,6 +276,28 @@ class IBugTarget(IHasBugs):
)
)
+ lp_templates = exported(
+ Dict(
+ title=("Templates to use for reporting a bug"),
+ description=(
+ "This pre-defined template will be given to the "
+ "users to guide them when reporting a bug. "
+ ),
+ key_type=TextLine(),
+ value_type=Dict(
+ key_type=TextLine(),
+ value_type=Text(
+ required=False,
+ max_length=50000,
+ ),
+ required=False,
+ max_length=50000,
+ ),
+ required=False,
+ max_length=50000,
+ )
+ )
+
bug_reported_acknowledgement = exported(
Text(
title=("After reporting a bug, I can expect the following."),
diff --git a/lib/lp/bugs/model/bugtarget.py b/lib/lp/bugs/model/bugtarget.py
index 2778def..4f84a4e 100644
--- a/lib/lp/bugs/model/bugtarget.py
+++ b/lib/lp/bugs/model/bugtarget.py
@@ -10,6 +10,7 @@ __all__ = [
"OfficialBugTagTargetMixin",
]
+
from storm.locals import Int, Reference, Unicode
from zope.component import getUtility
from zope.interface import implementer
@@ -119,6 +120,9 @@ class BugTargetBase(HasBugsBase):
# IDistribution, IDistroSeries, IProjectGroup.
enable_bugfiling_duplicate_search = True
+ # Field to store the templates as a JSON structure
+ # templates = Unicode("templates")
+
def getUsedBugTagsWithOpenCounts(
self, user, tag_limit=0, include_tags=None
):
@@ -139,6 +143,14 @@ class BugTargetBase(HasBugsBase):
params.target = self
return getUtility(IBugSet).createBug(params)
+ # def getTemplates(self):
+ # """Retrieve the template"""
+ # return json.loads(self.templates)
+
+ # def setTemplates(self, new_templates):
+ # """Set the templates field"""
+ # self.templates = json.dumps(new_templates)
+
class OfficialBugTagTargetMixin:
"""See `IOfficialBugTagTarget`.
diff --git a/lib/lp/bugs/stories/bug-privacy/xx-presenting-private-bugs.rst b/lib/lp/bugs/stories/bug-privacy/xx-presenting-private-bugs.rst
index bc1affa..f8a800d 100644
--- a/lib/lp/bugs/stories/bug-privacy/xx-presenting-private-bugs.rst
+++ b/lib/lp/bugs/stories/bug-privacy/xx-presenting-private-bugs.rst
@@ -36,7 +36,7 @@ have the full message:
... )
>>> browser.getControl("Continue").click()
- >>> browser.getControl("Further information").value = "foo"
+ >>> browser.getControl("Bug Description").value = "foo"
>>> browser.getControl("Private Security").selected = True
>>> browser.getControl("Submit Bug Report").click()
diff --git a/lib/lp/bugs/stories/bugs/xx-add-comment-distribution-no-current-release.rst b/lib/lp/bugs/stories/bugs/xx-add-comment-distribution-no-current-release.rst
index 6657ce5..c38e11c 100644
--- a/lib/lp/bugs/stories/bugs/xx-add-comment-distribution-no-current-release.rst
+++ b/lib/lp/bugs/stories/bugs/xx-add-comment-distribution-no-current-release.rst
@@ -7,7 +7,7 @@ it's still possible to add comments to the bug.
>>> user_browser.open("http://launchpad.test/gentoo/+filebug")
>>> user_browser.getControl("Summary", index=0).value = "Test bug"
>>> user_browser.getControl("Continue").click()
- >>> user_browser.getControl("Further information").value = "A test bug."
+ >>> user_browser.getControl("Bug Description").value = "A test bug."
>>> user_browser.getControl("Submit Bug Report").click()
>>> user_browser.url
'http://bugs.launchpad.test/gentoo/+bug/...'
diff --git a/lib/lp/bugs/stories/bugtask-searches/xx-advanced-people-filters.rst b/lib/lp/bugs/stories/bugtask-searches/xx-advanced-people-filters.rst
index 2122ce7..4f27105 100644
--- a/lib/lp/bugs/stories/bugtask-searches/xx-advanced-people-filters.rst
+++ b/lib/lp/bugs/stories/bugtask-searches/xx-advanced-people-filters.rst
@@ -232,7 +232,7 @@ product:
>>> browser.getControl("Summary", index=0).value = "Test Bug 1"
>>> browser.getControl("Continue").click()
- >>> browser.getControl("Further information").value = "Test Bug 1"
+ >>> browser.getControl("Bug Description").value = "Test Bug 1"
>>> browser.getControl("Submit").click()
>>> print_feedback_messages(browser.contents)
Thank you for your bug report...
@@ -242,7 +242,7 @@ product:
>>> browser.open(report_bug_url)
>>> browser.getControl("Summary", index=0).value = "Test Bug 2"
>>> browser.getControl("Continue").click()
- >>> browser.getControl("Further information").value = "Test Bug 2"
+ >>> browser.getControl("Bug Description").value = "Test Bug 2"
>>> browser.getControl("Submit").click()
>>> print_feedback_messages(browser.contents)
Thank you for your bug report...
diff --git a/lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-guidelines.rst b/lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-guidelines.rst
index f22fc18..51817ad 100644
--- a/lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-guidelines.rst
+++ b/lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-guidelines.rst
@@ -1,10 +1,10 @@
-Bug Reporting Guidelines and acknowledgement messages
+Bug Reporting Guidelines, Acknowledgement Messages and Description Templates
=====================================================
-Some helpful explanatory text - guidelines - can be set for
-distributions, product groups, products, and source packages, as well
-as an acknowledgement message that is displayed when a bug has been
-filed.
+Some helpful explanatory text - guidelines - and a pre-defined bug description
+template can be set for distributions, product groups, products, and source
+packages, as well as an acknowledgement message that is displayed when a bug
+has been filed.
>>> contexts = [
... ("Ubuntu", "ubuntu", "+edit"),
@@ -22,6 +22,9 @@ filed.
... "The version of %s you're using.\n"
... "See http://example.com for more details." % (context_name,)
... )
+ ... admin_browser.getControl(name="field.lp_templates").value = (
+ ... "The pre-defined bug template."
+ ... )
... admin_browser.getControl(
... name="field.bug_reported_acknowledgement"
... ).value = (
@@ -34,8 +37,9 @@ filed.
... admin_browser.getControl("Change").click()
...
-The guidelines are not displayed on the initial basic bug-reporting
-page, because that page does not include a bug description field.
+The guidelines and bug templates are not displayed on the initial basic
+bug-reporting page, because that page does not include a bug description
+field.
>>> def print_guidelines(name, browser):
... print("*")
@@ -96,9 +100,7 @@ description.
... "It doesn't work"
... )
... user_browser.getControl("Continue").click()
- ... user_browser.getControl("Further information").value = (
- ... "please help!"
- ... )
+ ... user_browser.getControl("Bug Description").value = "please help!"
... print_guidelines(context_name, user_browser)
... user_browser.getControl("Submit Bug Report").click()
... print_acknowledgement_message(user_browser)
@@ -230,11 +232,12 @@ as bug #297743, "When filing a bug always display the appropriate
reporting guidelines".
-Editing the guidelines
+Editing the guidelines and description template.
----------------------
Unprivileged Launchpad users do not see the link to the page where the
-bug reporting guidelines can be changed, but admins do.
+bug reporting guidelines and the bug description template can be changed,
+but admins do.
>>> import re
>>> import sys
@@ -270,8 +273,8 @@ bug reporting guidelines can be changed, but admins do.
- User: LinkNotFoundError
- Admin: True
-Unprivileged cannot access the page for changing bug reporting
-guidelines.
+Unprivileged cannot access the page for changing the bug reporting
+guidelines and the bug template.
>>> for context_name, context_path, view in contexts:
... edit_url = "http://launchpad.test/%s/%s" % (context_path, view)
diff --git a/lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-tools.rst b/lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-tools.rst
index 68642d6..c853bed 100644
--- a/lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-tools.rst
+++ b/lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-tools.rst
@@ -119,7 +119,7 @@ be on the same URL, with the token present.
Even if the form has errors the token will be present in the URL.
- >>> user_browser.getControl("Further information").value
+ >>> user_browser.getControl("Bug Description").value
''
>>> user_browser.getControl("Submit Bug Report").click()
>>> for error in find_tags_by_class(
@@ -134,7 +134,7 @@ Even if the form has errors the token will be present in the URL.
If we go ahead submitting the bug, the bug will have all the extra
information specified in the extra filebug data.
- >>> user_browser.getControl("Further information").value = (
+ >>> user_browser.getControl("Bug Description").value = (
... "A bug description."
... )
>>> user_browser.getControl("Submit Bug Report").click()
@@ -233,9 +233,7 @@ The user can of course change the tags if they want.
>>> user_browser.getControl("Tags").value = "bar baz"
>>> user_browser.getControl("Summary", index=0).value = "Bug Summary"
- >>> user_browser.getControl("Further information").value = (
- ... "Bug description."
- ... )
+ >>> user_browser.getControl("Bug Description").value = "Bug description."
>>> user_browser.getControl("Submit Bug Report").click()
>>> user_browser.url
'http://bugs.launchpad.test/ubuntu/+source/mozilla-firefox/+bug/...'
@@ -254,9 +252,7 @@ that will get their tags set as well.
>>> user_browser.getControl("Summary", index=0).value = "Bug Summary"
>>> user_browser.getControl("Continue").click()
- >>> user_browser.getControl("Further information").value = (
- ... "Bug description."
- ... )
+ >>> user_browser.getControl("Bug Description").value = "Bug description."
>>> user_browser.getControl("Submit Bug Report").click()
>>> user_browser.url
'http://bugs.launchpad.test/ubuntu/+source/mozilla-firefox/+bug/...'
diff --git a/lib/lp/bugs/stories/guided-filebug/xx-distro-guided-filebug-tags.rst b/lib/lp/bugs/stories/guided-filebug/xx-distro-guided-filebug-tags.rst
index 7dd3c82..27f9d8b 100644
--- a/lib/lp/bugs/stories/guided-filebug/xx-distro-guided-filebug-tags.rst
+++ b/lib/lp/bugs/stories/guided-filebug/xx-distro-guided-filebug-tags.rst
@@ -28,7 +28,7 @@ After submitting the bug, the tags are added to the bug.
>>> from lp.bugs.tests.bug import print_bug_tag_anchors
- >>> user_browser.getControl("Further information").value = "Thanks."
+ >>> user_browser.getControl("Bug Description").value = "Thanks."
>>> user_browser.getControl("Submit Bug Report").click()
>>> user_browser.url
diff --git a/lib/lp/bugs/stories/guided-filebug/xx-distro-guided-filebug.rst b/lib/lp/bugs/stories/guided-filebug/xx-distro-guided-filebug.rst
index 8df2c97..2a5ced7 100644
--- a/lib/lp/bugs/stories/guided-filebug/xx-distro-guided-filebug.rst
+++ b/lib/lp/bugs/stories/guided-filebug/xx-distro-guided-filebug.rst
@@ -53,9 +53,9 @@ back...
>>> user_browser.getControl(name="packagename_option").value = ["choose"]
>>> user_browser.getControl("In what package").value = "mozilla-firefox"
>>> user_browser.getControl("Summary", index=0).value = "a new ubuntu bug"
- >>> user_browser.getControl("Further information").value = "test"
+ >>> user_browser.getControl("Bug Description").value = "test"
-The comment field ("Further information") is not optional when
+The comment field ("Bug Description") is not optional when
filing a bug, but it is optional when subscribing to a similar
bug. Nevertheless, we don't show an "(Optional)" hint next to the
description.
@@ -64,12 +64,12 @@ description.
>>> page_soup = find_main_content(user_browser.contents)
>>> field_labels = page_soup.find_all(
- ... "label", text=re.compile("Further information")
+ ... "label", text=re.compile("Bug Description")
... )
>>> for field_label in field_labels:
... print(extract_text(field_label.parent))
...
- Further information:
+ Bug Description:
Finally, let's submit the bug.
@@ -107,7 +107,7 @@ But the bug can be filed as before.
>>> user_browser.getControl(name="packagename_option").value = ["choose"]
>>> user_browser.getControl("In what package").value = "mozilla-firefox"
- >>> user_browser.getControl("Further information").value = (
+ >>> user_browser.getControl("Bug Description").value = (
... "Frobnobulator is a Firefox add-on, ..."
... )
>>> user_browser.getControl("Submit Bug Report").click()
diff --git a/lib/lp/bugs/stories/guided-filebug/xx-filebug-attachments.rst b/lib/lp/bugs/stories/guided-filebug/xx-filebug-attachments.rst
index 32baa95..d1afe24 100644
--- a/lib/lp/bugs/stories/guided-filebug/xx-filebug-attachments.rst
+++ b/lib/lp/bugs/stories/guided-filebug/xx-filebug-attachments.rst
@@ -17,7 +17,7 @@ guided filebug form.
... "A totally new " "bug with attachments"
... )
>>> user_browser.getControl("Continue").click()
- >>> user_browser.getControl("Further information").value = (
+ >>> user_browser.getControl("Bug Description").value = (
... "We can now add attachments!"
... )
@@ -31,7 +31,7 @@ a file-like object to demonstrate this.
>>> user_browser.getControl("Attachment").add_file(
... example_file, "text/plain", "example.txt"
... )
- >>> user_browser.getControl("Description").value = (
+ >>> user_browser.getControl("Description", index=1).value = (
... "A description " "of the attachment"
... )
>>> user_browser.getControl("Submit Bug Report").click()
diff --git a/lib/lp/bugs/stories/guided-filebug/xx-filebug-tags.rst b/lib/lp/bugs/stories/guided-filebug/xx-filebug-tags.rst
index f708dd6..a97987b 100644
--- a/lib/lp/bugs/stories/guided-filebug/xx-filebug-tags.rst
+++ b/lib/lp/bugs/stories/guided-filebug/xx-filebug-tags.rst
@@ -14,9 +14,7 @@ is being filed.
>>> user_browser.getControl("Summary", index=0).value = "Bug with tags"
>>> user_browser.getControl("Continue").click()
>>> user_browser.getControl("Tags").value = "foo bar"
- >>> user_browser.getControl("Further information").value = (
- ... "This bug has tags"
- ... )
+ >>> user_browser.getControl("Bug Description").value = "This bug has tags"
>>> user_browser.getControl("Submit Bug Report").click()
>>> user_browser.url
'http://bugs.launchpad.test/firefox/+bug/...'
diff --git a/lib/lp/bugs/stories/guided-filebug/xx-options-for-bug-supervisors.rst b/lib/lp/bugs/stories/guided-filebug/xx-options-for-bug-supervisors.rst
index 89115ab..b60cd93 100644
--- a/lib/lp/bugs/stories/guided-filebug/xx-options-for-bug-supervisors.rst
+++ b/lib/lp/bugs/stories/guided-filebug/xx-options-for-bug-supervisors.rst
@@ -65,7 +65,7 @@ Using these extra options
>>> user_browser.open("http://bugs.launchpad.test/firefox/+filebug")
>>> user_browser.getControl("Summary", index=0).value = "Bug"
>>> user_browser.getControl("Continue").click()
- >>> user_browser.getControl("Further information").value = "Blah"
+ >>> user_browser.getControl("Bug Description").value = "Blah"
A bug supervisor can set the status, importance, milestone, and/or
assignee, and the bug will be filed with those choices.
diff --git a/lib/lp/bugs/stories/guided-filebug/xx-product-guided-filebug.rst b/lib/lp/bugs/stories/guided-filebug/xx-product-guided-filebug.rst
index dda726f..2af51fd 100644
--- a/lib/lp/bugs/stories/guided-filebug/xx-product-guided-filebug.rst
+++ b/lib/lp/bugs/stories/guided-filebug/xx-product-guided-filebug.rst
@@ -57,7 +57,7 @@ file the bug.
If the user for some reason would erase the summary, an error message
will be displayed as well.
- >>> user_browser.getControl("Further information").value = "not empty"
+ >>> user_browser.getControl("Bug Description").value = "not empty"
>>> user_browser.getControl("Summary", index=0).value = ""
>>> user_browser.getControl("Submit Bug Report").click()
>>> print(user_browser.url)
@@ -76,7 +76,7 @@ will be displayed as well.
With both values set, the bug is created.
>>> user_browser.getControl("Summary", index=0).value = "a brand new bug"
- >>> user_browser.getControl("Further information").value = "test"
+ >>> user_browser.getControl("Bug Description").value = "test"
>>> user_browser.getControl("Submit Bug Report").click()
>>> print(user_browser.url)
@@ -167,7 +167,7 @@ shown.
But, as before, entering a description and submitting the bug takes the
user to the bug page.
- >>> user_browser.getControl("Further information").value = (
+ >>> user_browser.getControl("Bug Description").value = (
... "Frankenzombulon is only meant to check my mail."
... )
>>> user_browser.getControl("Submit Bug Report").click()
diff --git a/lib/lp/bugs/stories/guided-filebug/xx-project-guided-filebug.rst b/lib/lp/bugs/stories/guided-filebug/xx-project-guided-filebug.rst
index 34478f3..edb200a 100644
--- a/lib/lp/bugs/stories/guided-filebug/xx-project-guided-filebug.rst
+++ b/lib/lp/bugs/stories/guided-filebug/xx-project-guided-filebug.rst
@@ -35,7 +35,7 @@ product's +filebug page to search for duplicates.
Entering a description and submitting the bug takes the user to the bug
page.
- >>> user_browser.getControl("Further information").value = "Crash."
+ >>> user_browser.getControl("Bug Description").value = "Crash."
>>> user_browser.getControl("Submit Bug Report").click()
>>> user_browser.url
'http://bugs.launchpad.test/evolution/+bug/...'
diff --git a/lib/lp/registry/browser/distribution.py b/lib/lp/registry/browser/distribution.py
index 711f141..fdb3d91 100644
--- a/lib/lp/registry/browser/distribution.py
+++ b/lib/lp/registry/browser/distribution.py
@@ -1148,6 +1148,7 @@ class DistributionEditView(
"summary",
"description",
"bug_reporting_guidelines",
+ "lp_templates",
"bug_reported_acknowledgement",
"package_derivatives_email",
"icon",
diff --git a/lib/lp/registry/browser/distributionsourcepackage.py b/lib/lp/registry/browser/distributionsourcepackage.py
index 5590db8..c686ce8 100644
--- a/lib/lp/registry/browser/distributionsourcepackage.py
+++ b/lib/lp/registry/browser/distributionsourcepackage.py
@@ -681,6 +681,7 @@ class DistributionSourcePackageEditView(LaunchpadEditFormView):
schema = IDistributionSourcePackage
field_names = [
"bug_reporting_guidelines",
+ "lp_templates",
"bug_reported_acknowledgement",
"enable_bugfiling_duplicate_search",
]
diff --git a/lib/lp/registry/browser/project.py b/lib/lp/registry/browser/project.py
index 5658659..afd8135 100644
--- a/lib/lp/registry/browser/project.py
+++ b/lib/lp/registry/browser/project.py
@@ -392,6 +392,7 @@ class ProjectEditView(LaunchpadEditFormView):
"summary",
"description",
"bug_reporting_guidelines",
+ "lp_templates",
"bug_reported_acknowledgement",
"homepageurl",
"bugtracker",
diff --git a/lib/lp/registry/browser/tests/distribution-views.rst b/lib/lp/registry/browser/tests/distribution-views.rst
index 2edfb50..413fefd 100644
--- a/lib/lp/registry/browser/tests/distribution-views.rst
+++ b/lib/lp/registry/browser/tests/distribution-views.rst
@@ -131,7 +131,8 @@ The view accepts most of the distribution fields.
>>> view.field_names
['display_name', 'summary', 'description',
- 'bug_reporting_guidelines', 'bug_reported_acknowledgement',
+ 'bug_reporting_guidelines', 'lp_templates',
+ 'bug_reported_acknowledgement',
'package_derivatives_email', 'icon',
'logo', 'mugshot', 'official_malone', 'enable_bug_expiration',
'blueprints_usage', 'translations_usage', 'answers_usage',
diff --git a/lib/lp/registry/browser/tests/distributionsourcepackage-views.rst b/lib/lp/registry/browser/tests/distributionsourcepackage-views.rst
index 83b2ff2..b2ed566 100644
--- a/lib/lp/registry/browser/tests/distributionsourcepackage-views.rst
+++ b/lib/lp/registry/browser/tests/distributionsourcepackage-views.rst
@@ -214,7 +214,8 @@ view provides a label, page_title and cancel_url.
The view allows the user the set the bug_reporting_guidelines field.
>>> view.field_names
- ['bug_reporting_guidelines', 'bug_reported_acknowledgement',
+ ['bug_reporting_guidelines', 'lp_templates',
+ 'bug_reported_acknowledgement',
'enable_bugfiling_duplicate_search']
>>> print(package.bug_reporting_guidelines)
diff --git a/lib/lp/registry/configure.zcml b/lib/lp/registry/configure.zcml
index 041e557..e4f12f1 100644
--- a/lib/lp/registry/configure.zcml
+++ b/lib/lp/registry/configure.zcml
@@ -580,6 +580,7 @@
set_attributes="
bug_reported_acknowledgement
bug_reporting_guidelines
+ lp_templates
enable_bugfiling_duplicate_search
"/>
</class>
@@ -1447,6 +1448,7 @@
enable_bugfiling_duplicate_search
bug_reported_acknowledgement
bug_reporting_guidelines
+ lp_templates
bugtracker
enable_bug_expiration
official_bug_tags
@@ -1505,6 +1507,7 @@
attributes="
bug_reported_acknowledgement
bug_reporting_guidelines
+ lp_templates
bugtargetname
createBug
enable_bugfiling_duplicate_search"/>
@@ -1749,6 +1752,7 @@
attributes="
bug_reported_acknowledgement
bug_reporting_guidelines
+ lp_templates
bugtargetname
createBug
enable_bugfiling_duplicate_search
@@ -1834,6 +1838,7 @@
set_attributes="
bug_reported_acknowledgement
bug_reporting_guidelines
+ lp_templates
code_admin
default_traversal_policy
description
diff --git a/lib/lp/registry/interfaces/ociproject.py b/lib/lp/registry/interfaces/ociproject.py
index 177f91f..07222c4 100644
--- a/lib/lp/registry/interfaces/ociproject.py
+++ b/lib/lp/registry/interfaces/ociproject.py
@@ -325,6 +325,7 @@ class IOCIProjectSet(Interface):
date_created=None,
description=None,
bug_reporting_guidelines=None,
+ lp_templates=None,
bug_reported_acknowledgement=None,
bugfiling_duplicate_search=False,
):
diff --git a/lib/lp/registry/interfaces/projectgroup.py b/lib/lp/registry/interfaces/projectgroup.py
index 0c760d6..aeb2e73 100644
--- a/lib/lp/registry/interfaces/projectgroup.py
+++ b/lib/lp/registry/interfaces/projectgroup.py
@@ -23,7 +23,7 @@ from lazr.restful.declarations import (
from lazr.restful.fields import CollectionField, Reference, ReferenceChoice
from lazr.restful.interface import copy_field
from zope.interface import Attribute, Interface
-from zope.schema import Bool, Datetime, Int, Object, Text, TextLine
+from zope.schema import Bool, Datetime, Dict, Int, Object, Text, TextLine
from lp import _
from lp.app.interfaces.launchpad import (
@@ -384,6 +384,28 @@ class IProjectGroupPublic(
)
)
+ lp_templates = exported(
+ Dict(
+ title=("Templates to use for reporting a bug"),
+ description=(
+ "This pre-defined template will be given to the "
+ "users to guide them when reporting a bug. "
+ ),
+ key_type=TextLine(),
+ value_type=Dict(
+ key_type=TextLine(),
+ value_type=Text(
+ required=False,
+ max_length=50000,
+ ),
+ required=False,
+ max_length=50000,
+ ),
+ required=False,
+ max_length=50000,
+ )
+ )
+
bug_reported_acknowledgement = exported(
Text(
title=("After reporting a bug, I can expect the following."),
diff --git a/lib/lp/registry/model/distribution.py b/lib/lp/registry/model/distribution.py
index 62ee160..0542e8f 100644
--- a/lib/lp/registry/model/distribution.py
+++ b/lib/lp/registry/model/distribution.py
@@ -13,6 +13,7 @@ from collections import defaultdict
from datetime import datetime, timedelta, timezone
from operator import itemgetter
+from storm.databases.postgres import JSON
from storm.expr import (
SQL,
And,
@@ -277,6 +278,7 @@ class Distribution(
)
bug_supervisor = Reference(bug_supervisor_id, "Person.id")
bug_reporting_guidelines = Unicode(default=None)
+ lp_templates = JSON(name="lp_templates", default=None)
bug_reported_acknowledgement = Unicode(default=None)
driver_id = Int(
name="driver",
diff --git a/lib/lp/registry/model/distributionsourcepackage.py b/lib/lp/registry/model/distributionsourcepackage.py
index 5d00db5..2f77dc4 100644
--- a/lib/lp/registry/model/distributionsourcepackage.py
+++ b/lib/lp/registry/model/distributionsourcepackage.py
@@ -15,6 +15,7 @@ from threading import local
import six
import transaction
from breezy.lru_cache import LRUCache
+from storm.databases.postgres import JSON
from storm.expr import And, Cast, Desc
from storm.locals import SQL, Bool, Int, Not, Reference, Store, Unicode
from zope.interface import implementer
@@ -101,6 +102,7 @@ class DistributionSourcePackage(
bug_reporting_guidelines = DistributionSourcePackageProperty(
"bug_reporting_guidelines"
)
+ lp_templates = DistributionSourcePackageProperty("lp_templates")
bug_reported_acknowledgement = DistributionSourcePackageProperty(
"bug_reported_acknowledgement"
)
@@ -605,6 +607,7 @@ class DistributionSourcePackageInDatabase(StormBase):
sourcepackagename = Reference(sourcepackagename_id, "SourcePackageName.id")
bug_reporting_guidelines = Unicode()
+ lp_templates = JSON()
bug_reported_acknowledgement = Unicode()
bug_count = Int()
diff --git a/lib/lp/registry/model/distroseries.py b/lib/lp/registry/model/distroseries.py
index 78283b9..b1becc1 100644
--- a/lib/lp/registry/model/distroseries.py
+++ b/lib/lp/registry/model/distroseries.py
@@ -800,6 +800,11 @@ class DistroSeries(
return self.distribution.bug_reporting_guidelines
@property
+ def lp_templates(self):
+ """See 'IBugTarget'."""
+ return self.distribution.lp_templates
+
+ @property
def bug_reported_acknowledgement(self):
"""See `IBugTarget`."""
return self.distribution.bug_reported_acknowledgement
diff --git a/lib/lp/registry/model/ociproject.py b/lib/lp/registry/model/ociproject.py
index e946258..b39f8af 100644
--- a/lib/lp/registry/model/ociproject.py
+++ b/lib/lp/registry/model/ociproject.py
@@ -11,6 +11,7 @@ __all__ = [
from collections import defaultdict
from datetime import timezone
+from storm.databases.postgres import JSON
from storm.expr import Join, LeftJoin, Or
from storm.locals import Bool, DateTime, Int, Reference, Unicode
from zope.component import getUtility
@@ -105,6 +106,7 @@ class OCIProject(BugTargetBase, StructuralSubscriptionTargetMixin, StormBase):
description = Unicode(name="description")
bug_reporting_guidelines = Unicode(name="bug_reporting_guidelines")
+ lp_templates = JSON(default=None)
bug_reported_acknowledgement = Unicode(name="bug_reported_acknowledgement")
enable_bugfiling_duplicate_search = Bool(
name="enable_bugfiling_duplicate_search"
@@ -412,6 +414,7 @@ class OCIProjectSet:
date_created=DEFAULT,
description=None,
bug_reporting_guidelines=None,
+ lp_templates=None,
bug_reported_acknowledgement=None,
bugfiling_duplicate_search=False,
):
@@ -427,6 +430,7 @@ class OCIProjectSet:
target.ociprojectname = name
target.description = description
target.bug_reporting_guidelines = bug_reporting_guidelines
+ target.lp_templates = lp_templates
target.bug_reported_acknowledgement = bug_reported_acknowledgement
target.enable_bugfiling_duplicate_search = bugfiling_duplicate_search
store.add(target)
diff --git a/lib/lp/registry/model/product.py b/lib/lp/registry/model/product.py
index 10bd4c6..079c3f2 100644
--- a/lib/lp/registry/model/product.py
+++ b/lib/lp/registry/model/product.py
@@ -17,6 +17,7 @@ from datetime import datetime, time, timedelta, timezone
from lazr.lifecycle.event import ObjectModifiedEvent
from lazr.restful.declarations import error_status
+from storm.databases.postgres import JSON
from storm.expr import (
SQL,
And,
@@ -736,6 +737,7 @@ class Product(
)
development_focus = Reference(development_focus_id, "ProductSeries.id")
bug_reporting_guidelines = Unicode(default=None)
+ lp_templates = JSON(name="lp_templates", default=None)
bug_reported_acknowledgement = Unicode(default=None)
enable_bugfiling_duplicate_search = Bool(allow_none=False, default=True)
diff --git a/lib/lp/registry/model/productseries.py b/lib/lp/registry/model/productseries.py
index 6651d16..5b33423 100644
--- a/lib/lp/registry/model/productseries.py
+++ b/lib/lp/registry/model/productseries.py
@@ -296,6 +296,11 @@ class ProductSeries(
return self.product.bug_reporting_guidelines
@property
+ def lp_templates(self):
+ """See `IBugTarget`."""
+ return self.product.lp_templates
+
+ @property
def bug_reported_acknowledgement(self):
"""See `IBugTarget`."""
return self.product.bug_reported_acknowledgement
diff --git a/lib/lp/registry/model/projectgroup.py b/lib/lp/registry/model/projectgroup.py
index 668be1d..9ea60aa 100644
--- a/lib/lp/registry/model/projectgroup.py
+++ b/lib/lp/registry/model/projectgroup.py
@@ -11,6 +11,7 @@ __all__ = [
from datetime import timezone
+from storm.databases.postgres import JSON
from storm.expr import And, Desc, Func, In, Is, Join, Min
from storm.locals import Bool, DateTime, Int, Reference, Unicode
from storm.store import Store
@@ -159,6 +160,7 @@ class ProjectGroup(
bugtracker_id = Int(name="bugtracker", allow_none=True, default=None)
bugtracker = Reference(bugtracker_id, "BugTracker.id")
bug_reporting_guidelines = Unicode(default=None)
+ lp_templates = JSON(default=None)
bug_reported_acknowledgement = Unicode(default=None)
def __init__(
diff --git a/lib/lp/registry/model/sourcepackage.py b/lib/lp/registry/model/sourcepackage.py
index 9186830..d9b0a93 100644
--- a/lib/lp/registry/model/sourcepackage.py
+++ b/lib/lp/registry/model/sourcepackage.py
@@ -483,6 +483,11 @@ class SourcePackage(
return self.distribution.bug_reporting_guidelines
@property
+ def lp_templates(self):
+ """See `IBugTarget`."""
+ return self.distribution.lp_templates
+
+ @property
def bug_reported_acknowledgement(self):
"""See `IBugTarget`."""
return self.distribution.bug_reported_acknowledgement
diff --git a/lib/lp/registry/stories/milestone/object-milestones.rst b/lib/lp/registry/stories/milestone/object-milestones.rst
index c349053..bf05c0c 100644
--- a/lib/lp/registry/stories/milestone/object-milestones.rst
+++ b/lib/lp/registry/stories/milestone/object-milestones.rst
@@ -210,7 +210,7 @@ Setup this embarrassing story.
>>> report_bug_url = browser.url
- >>> browser.getControl("Further information").value = "Test Bug 1"
+ >>> browser.getControl("Bug Description").value = "Test Bug 1"
>>> browser.getControl("Submit").click()
>>> print_feedback_messages(browser.contents)
Thank you for your bug report...
@@ -222,7 +222,7 @@ Setup this embarrassing story.
>>> browser.getControl("Summary", index=0).value = "Test Bug 2"
>>> browser.getControl("Continue").click()
- >>> browser.getControl("Further information").value = "Test Bug 2"
+ >>> browser.getControl("Bug Description").value = "Test Bug 2"
>>> browser.getControl("Submit").click()
>>> print_feedback_messages(browser.contents)
Thank you for your bug report...
diff --git a/lib/lp/registry/stories/webservice/xx-distribution-source-package.rst b/lib/lp/registry/stories/webservice/xx-distribution-source-package.rst
index a848237..f359f74 100644
--- a/lib/lp/registry/stories/webservice/xx-distribution-source-package.rst
+++ b/lib/lp/registry/stories/webservice/xx-distribution-source-package.rst
@@ -16,6 +16,7 @@ Source packages can be obtained from the context of a distribution.
bug_reporting_guidelines: None
display_name: 'mozilla-firefox in Debian'
distribution_link: 'http://.../debian'
+ lp_templates: None
name: 'mozilla-firefox'
official_bug_tags: []
resource_type_link: 'http://.../#distribution_source_package'
diff --git a/lib/lp/registry/stories/webservice/xx-distribution.rst b/lib/lp/registry/stories/webservice/xx-distribution.rst
index 1d9a8e9..f6c16b0 100644
--- a/lib/lp/registry/stories/webservice/xx-distribution.rst
+++ b/lib/lp/registry/stories/webservice/xx-distribution.rst
@@ -45,6 +45,7 @@ And for every distribution we publish most of its attributes.
icon_link: 'http://.../ubuntu/icon'
information_type: 'Public'
logo_link: 'http://.../ubuntu/logo'
+ lp_templates: None
main_archive_link: 'http://.../ubuntu/+archive/primary'
members_link: 'http://.../~ubuntu-team'
mirror_admin_link: 'http://.../~ubuntu-mirror-admins'
diff --git a/lib/lp/registry/stories/webservice/xx-distroseries.rst b/lib/lp/registry/stories/webservice/xx-distroseries.rst
index 51a089a..b75f5db 100644
--- a/lib/lp/registry/stories/webservice/xx-distroseries.rst
+++ b/lib/lp/registry/stories/webservice/xx-distroseries.rst
@@ -86,6 +86,7 @@ For distroseries we publish a subset of its attributes.
include_long_descriptions: True
index_compressors: ['gzip', 'bzip2']
language_pack_full_export_requested: False
+ lp_templates: None
main_archive_link: 'http://.../ubuntu/+archive/primary'
name: 'hoary'
nominatedarchindep_link: 'http://.../ubuntu/hoary/i386'
diff --git a/lib/lp/registry/stories/webservice/xx-person.rst b/lib/lp/registry/stories/webservice/xx-person.rst
index 7e93f8b..8d88aff 100644
--- a/lib/lp/registry/stories/webservice/xx-person.rst
+++ b/lib/lp/registry/stories/webservice/xx-person.rst
@@ -815,6 +815,7 @@ Subscribed packages can be listed with getBugSubscriberPackages:
bug_reporting_guidelines: None
display_name: '...'
distribution_link: '...'
+ lp_templates: None
name: 'fooix'
official_bug_tags: []
resource_type_link: '...'
diff --git a/lib/lp/registry/stories/webservice/xx-project-registry.rst b/lib/lp/registry/stories/webservice/xx-project-registry.rst
index 37b1061..5dbc0a2 100644
--- a/lib/lp/registry/stories/webservice/xx-project-registry.rst
+++ b/lib/lp/registry/stories/webservice/xx-project-registry.rst
@@ -88,6 +88,7 @@ host.
homepage_url: 'http://www.mozilla.org/'
icon_link: 'http://.../mozilla/icon'
logo_link: 'http://.../mozilla/logo'
+ lp_templates: None
mugshot_link: 'http://.../mozilla/mugshot'
name: 'mozilla'
official_bug_tags: []
@@ -193,6 +194,7 @@ Projects are available at their canonical URL on the API virtual host.
license_info: None
licenses: ['MIT / X / Expat Licence']
logo_link: 'http://.../firefox/logo'
+ lp_templates: None
name: 'firefox'
official_answers: True
official_blueprints: False
@@ -845,6 +847,7 @@ virtual host.
display_name: 'foobadoo'
driver_link: None
drivers_collection_link: 'http://.../babadoo/foobadoo/drivers'
+ lp_templates: None
name: 'foobadoo'
official_bug_tags: []
owner_link: 'http://.../~babadoo-owner'
diff --git a/lib/lp/registry/stories/webservice/xx-source-package.rst b/lib/lp/registry/stories/webservice/xx-source-package.rst
index d09785d..410e765 100644
--- a/lib/lp/registry/stories/webservice/xx-source-package.rst
+++ b/lib/lp/registry/stories/webservice/xx-source-package.rst
@@ -36,6 +36,7 @@ distribution series.
distribution_link: 'http://.../my-distro'
distroseries_link: 'http://.../my-distro/my-series'
latest_published_component_name: None
+ lp_templates: None
name: 'evolution'
official_bug_tags: []
productseries_link: None
diff --git a/lib/lp/registry/tests/test_product.py b/lib/lp/registry/tests/test_product.py
index faf885b..d182d75 100644
--- a/lib/lp/registry/tests/test_product.py
+++ b/lib/lp/registry/tests/test_product.py
@@ -977,6 +977,7 @@ class TestProduct(TestCaseWithFactory):
"blueprints_usage",
"branch_sharing_policy",
"bug_reported_acknowledgement",
+ "lp_templates",
"bug_reporting_guidelines",
"bug_sharing_policy",
"bug_subscriptions",
@@ -1145,6 +1146,7 @@ class TestProduct(TestCaseWithFactory):
expected_set_permissions = {
"launchpad.BugSupervisor": {
"bug_reported_acknowledgement",
+ "lp_templates",
"bug_reporting_guidelines",
"bugtracker",
"enable_bug_expiration",
diff --git a/lib/lp/registry/tests/test_productseries.py b/lib/lp/registry/tests/test_productseries.py
index 37d9d2f..611cf80 100644
--- a/lib/lp/registry/tests/test_productseries.py
+++ b/lib/lp/registry/tests/test_productseries.py
@@ -686,6 +686,7 @@ class ProductSeriesSecurityAdaperTestCase(TestCaseWithFactory):
"blueprints_usage",
"branch",
"bug_reported_acknowledgement",
+ "lp_templates",
"bug_reporting_guidelines",
"bug_subscriptions",
"bug_supervisor",
diff --git a/lib/lp/testing/factory.py b/lib/lp/testing/factory.py
index f47ba66..b0d1c40 100644
--- a/lib/lp/testing/factory.py
+++ b/lib/lp/testing/factory.py
@@ -6504,6 +6504,7 @@ class LaunchpadObjectFactory(ObjectFactory):
date_created=DEFAULT,
description=None,
bug_reporting_guidelines=None,
+ lp_templates=None,
bug_reported_acknowledgement=None,
bugfiling_duplicate_search=False,
):
@@ -6521,6 +6522,7 @@ class LaunchpadObjectFactory(ObjectFactory):
date_created=date_created,
description=description,
bug_reporting_guidelines=bug_reporting_guidelines,
+ lp_templates=lp_templates,
bug_reported_acknowledgement=bug_reported_acknowledgement,
bugfiling_duplicate_search=bugfiling_duplicate_search,
)
Follow ups