Merge lp:~wgrant/launchpad/rework-bug-default-type-1 into lp:launchpad
- rework-bug-default-type-1
- Merge into devel
Status: | Merged |
---|---|
Merged at revision: | 15725 |
Proposed branch: | lp:~wgrant/launchpad/rework-bug-default-type-1 |
Merge into: | lp:launchpad |
Prerequisite: | lp:~wgrant/launchpad/rework-bug-default-type-0 |
Diff against target: |
544 lines (+166/-254) 5 files modified
lib/lp/bugs/browser/bugtarget.py (+117/-140) lib/lp/bugs/browser/configure.zcml (+0/-6) lib/lp/bugs/browser/tests/test_bugtarget_filebug.py (+5/-55) lib/lp/bugs/templates/bugtarget-filebug-guidelines.pt (+0/-51) lib/lp/bugs/templates/bugtarget-macros-filebug.pt (+44/-2) |
To merge this branch: | bzr merge lp:~wgrant/launchpad/rework-bug-default-type-1 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Richard Harding (community) | Approve | ||
Review via email: mp+117380@code.launchpad.net |
Commit message
Merge FileBugReportin
Description of the change
This branch is the second in a series of maybe four to rework bug information type defaults, which will eventually allow us to default to Proprietary when a project is so configured.
Some awkwardness arose during UI refactoring due to the split between FileBugViewBase and FileBugReportin
The only minor awkwardness was that the form relies on the JSON request cache being fully populated, but form action templates are rendered in LaunchpadFormVi
Preview Diff
1 | === modified file 'lib/lp/bugs/browser/bugtarget.py' | |||
2 | --- lib/lp/bugs/browser/bugtarget.py 2012-07-31 05:46:45 +0000 | |||
3 | +++ lib/lp/bugs/browser/bugtarget.py 2012-08-01 01:08:21 +0000 | |||
4 | @@ -243,30 +243,40 @@ | |||
5 | 243 | self.updateContextFromData(data) | 243 | self.updateContextFromData(data) |
6 | 244 | 244 | ||
7 | 245 | 245 | ||
17 | 246 | class FileBugReportingGuidelines(LaunchpadFormView): | 246 | class FileBugViewBase(LaunchpadFormView): |
18 | 247 | """Provides access to common bug reporting attributes. | 247 | """Base class for views related to filing a bug.""" |
19 | 248 | 248 | ||
20 | 249 | Attributes provided are: information_type and bug_reporting_guidelines. | 249 | implements(IBrowserPublisher) |
12 | 250 | |||
13 | 251 | This view is a superclass of `FileBugViewBase` so that non-ajax browsers | ||
14 | 252 | can load the file bug form, and it is also invoked directly via an XHR | ||
15 | 253 | request to provide an HTML snippet for Javascript enabled browsers. | ||
16 | 254 | """ | ||
21 | 255 | 250 | ||
22 | 256 | schema = IBug | 251 | schema = IBug |
23 | 257 | 252 | ||
24 | 258 | @property | ||
25 | 259 | def field_names(self): | ||
26 | 260 | """Return the list of field names to display.""" | ||
27 | 261 | if self.is_bug_supervisor: | ||
28 | 262 | return ['information_type'] | ||
29 | 263 | else: | ||
30 | 264 | return ['security_related'] | ||
31 | 265 | |||
32 | 266 | custom_widget('information_type', LaunchpadRadioWidgetWithDescription) | 253 | custom_widget('information_type', LaunchpadRadioWidgetWithDescription) |
33 | 267 | 254 | ||
34 | 255 | extra_data_token = None | ||
35 | 256 | advanced_form = False | ||
36 | 257 | frontpage_form = False | ||
37 | 258 | data_parser = None | ||
38 | 259 | |||
39 | 260 | def __init__(self, context, request): | ||
40 | 261 | LaunchpadFormView.__init__(self, context, request) | ||
41 | 262 | self.extra_data = FileBugData() | ||
42 | 263 | |||
43 | 268 | def initialize(self): | 264 | def initialize(self): |
45 | 269 | super(FileBugReportingGuidelines, self).initialize() | 265 | # redirect_ubuntu_filebug is a cached_property. |
46 | 266 | # Access it first just to compute its value. Because it | ||
47 | 267 | # makes a DB access to get the bug supervisor, it causes | ||
48 | 268 | # trouble in tests when form validation errors occur. Because the | ||
49 | 269 | # transaction is doomed, the storm cache is invalidated and accessing | ||
50 | 270 | # the property will result in a a LostObjectError, because | ||
51 | 271 | # the created objects disappeared. Not likely a problem in production | ||
52 | 272 | # since the objects will still be in the DB, but doesn't hurt there | ||
53 | 273 | # either. It makes for better diagnosis of failing tests. | ||
54 | 274 | if self.redirect_ubuntu_filebug: | ||
55 | 275 | pass | ||
56 | 276 | |||
57 | 277 | # The JSON cache must be populated before the super call, since | ||
58 | 278 | # the form is rendered during LaunchpadFormView's initialize() | ||
59 | 279 | # when an action is invokved. | ||
60 | 270 | cache = IJSONRequestCache(self.request) | 280 | cache = IJSONRequestCache(self.request) |
61 | 271 | cache.objects['private_types'] = [ | 281 | cache.objects['private_types'] = [ |
62 | 272 | type.name for type in PRIVATE_INFORMATION_TYPES] | 282 | type.name for type in PRIVATE_INFORMATION_TYPES] |
63 | @@ -296,125 +306,12 @@ | |||
64 | 296 | css_class_prefix='importance', | 306 | css_class_prefix='importance', |
65 | 297 | excluded_items=[BugTaskImportance.UNKNOWN]) | 307 | excluded_items=[BugTaskImportance.UNKNOWN]) |
66 | 298 | cache.objects['bugtask_importance_data'] = bugtask_importance_data | 308 | cache.objects['bugtask_importance_data'] = bugtask_importance_data |
67 | 299 | |||
68 | 300 | def setUpFields(self): | ||
69 | 301 | """Set up the form fields. See `LaunchpadFormView`.""" | ||
70 | 302 | super(FileBugReportingGuidelines, self).setUpFields() | ||
71 | 303 | |||
72 | 304 | # Project groups are special. The Next button sends you to | ||
73 | 305 | # Product:+filebug, so we need none of the usual stuff. | ||
74 | 306 | if IProjectGroup.providedBy(self.context): | ||
75 | 307 | return | ||
76 | 308 | |||
77 | 309 | if self.is_bug_supervisor: | ||
78 | 310 | info_type_vocab = InformationTypeVocabulary( | ||
79 | 311 | types=self.context.pillar.getAllowedBugInformationTypes()) | ||
80 | 312 | information_type_field = copy_field( | ||
81 | 313 | IBug['information_type'], readonly=False, | ||
82 | 314 | vocabulary=info_type_vocab) | ||
83 | 315 | self.form_fields = self.form_fields.omit('information_type') | ||
84 | 316 | self.form_fields += Fields(information_type_field) | ||
85 | 317 | else: | ||
86 | 318 | security_related_field = copy_field( | ||
87 | 319 | IBug['security_related'], readonly=False) | ||
88 | 320 | self.form_fields = self.form_fields.omit('security_related') | ||
89 | 321 | self.form_fields += Fields(security_related_field) | ||
90 | 322 | |||
91 | 323 | @property | ||
92 | 324 | def initial_values(self): | ||
93 | 325 | """See `LaunchpadFormView`.""" | ||
94 | 326 | value = InformationType.PUBLIC | ||
95 | 327 | if (self.context and IProduct.providedBy(self.context) and | ||
96 | 328 | self.context.private_bugs): | ||
97 | 329 | value = InformationType.USERDATA | ||
98 | 330 | return {'information_type': value} | ||
99 | 331 | |||
100 | 332 | @property | ||
101 | 333 | def bug_reporting_guidelines(self): | ||
102 | 334 | """Guidelines for filing bugs in the current context. | ||
103 | 335 | |||
104 | 336 | Returns a list of dicts, with each dict containing values for | ||
105 | 337 | "preamble" and "content". | ||
106 | 338 | """ | ||
107 | 339 | |||
108 | 340 | def target_name(target): | ||
109 | 341 | # IProjectGroup can be considered the target of a bug during | ||
110 | 342 | # the bug filing process, but does not extend IBugTarget | ||
111 | 343 | # and ultimately cannot actually be the target of a | ||
112 | 344 | # bug. Hence this function to determine a suitable | ||
113 | 345 | # name/title to display. Hurrumph. | ||
114 | 346 | if IBugTarget.providedBy(target): | ||
115 | 347 | return target.bugtargetdisplayname | ||
116 | 348 | else: | ||
117 | 349 | return target.displayname | ||
118 | 350 | |||
119 | 351 | guidelines = [] | ||
120 | 352 | bugtarget = self.context | ||
121 | 353 | if bugtarget is not None: | ||
122 | 354 | content = bugtarget.bug_reporting_guidelines | ||
123 | 355 | if content is not None and len(content) > 0: | ||
124 | 356 | guidelines.append({ | ||
125 | 357 | "source": target_name(bugtarget), | ||
126 | 358 | "content": content, | ||
127 | 359 | }) | ||
128 | 360 | # Distribution source packages are shown with both their | ||
129 | 361 | # own reporting guidelines and those of their | ||
130 | 362 | # distribution. | ||
131 | 363 | if IDistributionSourcePackage.providedBy(bugtarget): | ||
132 | 364 | distribution = bugtarget.distribution | ||
133 | 365 | content = distribution.bug_reporting_guidelines | ||
134 | 366 | if content is not None and len(content) > 0: | ||
135 | 367 | guidelines.append({ | ||
136 | 368 | "source": target_name(distribution), | ||
137 | 369 | "content": content, | ||
138 | 370 | }) | ||
139 | 371 | return guidelines | ||
140 | 372 | |||
141 | 373 | def getMainContext(self): | ||
142 | 374 | if IDistributionSourcePackage.providedBy(self.context): | ||
143 | 375 | return self.context.distribution | ||
144 | 376 | else: | ||
145 | 377 | return self.context | ||
146 | 378 | |||
147 | 379 | @cachedproperty | ||
148 | 380 | def is_bug_supervisor(self): | ||
149 | 381 | """ Return True if the logged in user is a bug supervisor.""" | ||
150 | 382 | context = self.getMainContext() | ||
151 | 383 | return BugTask.userHasBugSupervisorPrivilegesContext( | ||
152 | 384 | context, self.user) | ||
153 | 385 | |||
154 | 386 | |||
155 | 387 | class FileBugViewBase(FileBugReportingGuidelines, LaunchpadFormView): | ||
156 | 388 | """Base class for views related to filing a bug.""" | ||
157 | 389 | |||
158 | 390 | implements(IBrowserPublisher) | ||
159 | 391 | |||
160 | 392 | extra_data_token = None | ||
161 | 393 | advanced_form = False | ||
162 | 394 | frontpage_form = False | ||
163 | 395 | data_parser = None | ||
164 | 396 | |||
165 | 397 | def __init__(self, context, request): | ||
166 | 398 | LaunchpadFormView.__init__(self, context, request) | ||
167 | 399 | self.extra_data = FileBugData() | ||
168 | 400 | |||
169 | 401 | def initialize(self): | ||
170 | 402 | # redirect_ubuntu_filebug is a cached_property. | ||
171 | 403 | # Access it first just to compute its value. Because it | ||
172 | 404 | # makes a DB access to get the bug supervisor, it causes | ||
173 | 405 | # trouble in tests when form validation errors occur. Because the | ||
174 | 406 | # transaction is doomed, the storm cache is invalidated and accessing | ||
175 | 407 | # the property will result in a a LostObjectError, because | ||
176 | 408 | # the created objects disappeared. Not likely a problem in production | ||
177 | 409 | # since the objects will still be in the DB, but doesn't hurt there | ||
178 | 410 | # either. It makes for better diagnosis of failing tests. | ||
179 | 411 | if self.redirect_ubuntu_filebug: | ||
180 | 412 | pass | ||
181 | 413 | super(FileBugViewBase, self).initialize() | ||
182 | 414 | cache = IJSONRequestCache(self.request) | ||
183 | 415 | cache.objects['enable_bugfiling_duplicate_search'] = ( | 309 | cache.objects['enable_bugfiling_duplicate_search'] = ( |
184 | 416 | IProjectGroup.providedBy(self.context) | 310 | IProjectGroup.providedBy(self.context) |
185 | 417 | or self.context.enable_bugfiling_duplicate_search) | 311 | or self.context.enable_bugfiling_duplicate_search) |
186 | 312 | |||
187 | 313 | super(FileBugViewBase, self).initialize() | ||
188 | 314 | |||
189 | 418 | if (self.extra_data_token is not None and | 315 | if (self.extra_data_token is not None and |
190 | 419 | not self.extra_data_to_process): | 316 | not self.extra_data_to_process): |
191 | 420 | # self.extra_data has been initialized in publishTraverse(). | 317 | # self.extra_data has been initialized in publishTraverse(). |
192 | @@ -492,10 +389,17 @@ | |||
193 | 492 | @property | 389 | @property |
194 | 493 | def initial_values(self): | 390 | def initial_values(self): |
195 | 494 | """Give packagename a default value, if applicable.""" | 391 | """Give packagename a default value, if applicable.""" |
200 | 495 | if not IDistributionSourcePackage.providedBy(self.context): | 392 | if (self.context and IProduct.providedBy(self.context) |
201 | 496 | return {} | 393 | and self.context.private_bugs): |
202 | 497 | 394 | type = InformationType.USERDATA | |
203 | 498 | return {'packagename': self.context.name} | 395 | else: |
204 | 396 | type = InformationType.PUBLIC | ||
205 | 397 | values = {'information_type': type} | ||
206 | 398 | |||
207 | 399 | if IDistributionSourcePackage.providedBy(self.context): | ||
208 | 400 | values['packagename'] = self.context.name | ||
209 | 401 | |||
210 | 402 | return values | ||
211 | 499 | 403 | ||
212 | 500 | def contextIsProduct(self): | 404 | def contextIsProduct(self): |
213 | 501 | return IProduct.providedBy(self.context) | 405 | return IProduct.providedBy(self.context) |
214 | @@ -588,7 +492,7 @@ | |||
215 | 588 | 492 | ||
216 | 589 | def setUpWidgets(self): | 493 | def setUpWidgets(self): |
217 | 590 | """Customize the onKeyPress event of the package name chooser.""" | 494 | """Customize the onKeyPress event of the package name chooser.""" |
219 | 591 | LaunchpadFormView.setUpWidgets(self) | 495 | super(FileBugViewBase, self).setUpWidgets() |
220 | 592 | 496 | ||
221 | 593 | if "packagename" in self.field_names: | 497 | if "packagename" in self.field_names: |
222 | 594 | self.widgets["packagename"].onKeyPress = ( | 498 | self.widgets["packagename"].onKeyPress = ( |
223 | @@ -598,6 +502,25 @@ | |||
224 | 598 | """Set up the form fields. See `LaunchpadFormView`.""" | 502 | """Set up the form fields. See `LaunchpadFormView`.""" |
225 | 599 | super(FileBugViewBase, self).setUpFields() | 503 | super(FileBugViewBase, self).setUpFields() |
226 | 600 | 504 | ||
227 | 505 | # Project groups are special. The Next button sends you to | ||
228 | 506 | # Product:+filebug, so we need none of the usual stuff. | ||
229 | 507 | if IProjectGroup.providedBy(self.context): | ||
230 | 508 | return | ||
231 | 509 | |||
232 | 510 | if self.is_bug_supervisor: | ||
233 | 511 | info_type_vocab = InformationTypeVocabulary( | ||
234 | 512 | types=self.context.pillar.getAllowedBugInformationTypes()) | ||
235 | 513 | information_type_field = copy_field( | ||
236 | 514 | IBug['information_type'], readonly=False, | ||
237 | 515 | vocabulary=info_type_vocab) | ||
238 | 516 | self.form_fields = self.form_fields.omit('information_type') | ||
239 | 517 | self.form_fields += Fields(information_type_field) | ||
240 | 518 | else: | ||
241 | 519 | security_related_field = copy_field( | ||
242 | 520 | IBug['security_related'], readonly=False) | ||
243 | 521 | self.form_fields = self.form_fields.omit('security_related') | ||
244 | 522 | self.form_fields += Fields(security_related_field) | ||
245 | 523 | |||
246 | 601 | # Override the vocabulary for the subscribe_to_existing_bug | 524 | # Override the vocabulary for the subscribe_to_existing_bug |
247 | 602 | # field. | 525 | # field. |
248 | 603 | subscribe_field = Choice( | 526 | subscribe_field = Choice( |
249 | @@ -1017,6 +940,60 @@ | |||
250 | 1017 | else: | 940 | else: |
251 | 1018 | return True | 941 | return True |
252 | 1019 | 942 | ||
253 | 943 | @property | ||
254 | 944 | def bug_reporting_guidelines(self): | ||
255 | 945 | """Guidelines for filing bugs in the current context. | ||
256 | 946 | |||
257 | 947 | Returns a list of dicts, with each dict containing values for | ||
258 | 948 | "preamble" and "content". | ||
259 | 949 | """ | ||
260 | 950 | |||
261 | 951 | def target_name(target): | ||
262 | 952 | # IProjectGroup can be considered the target of a bug during | ||
263 | 953 | # the bug filing process, but does not extend IBugTarget | ||
264 | 954 | # and ultimately cannot actually be the target of a | ||
265 | 955 | # bug. Hence this function to determine a suitable | ||
266 | 956 | # name/title to display. Hurrumph. | ||
267 | 957 | if IBugTarget.providedBy(target): | ||
268 | 958 | return target.bugtargetdisplayname | ||
269 | 959 | else: | ||
270 | 960 | return target.displayname | ||
271 | 961 | |||
272 | 962 | guidelines = [] | ||
273 | 963 | bugtarget = self.context | ||
274 | 964 | if bugtarget is not None: | ||
275 | 965 | content = bugtarget.bug_reporting_guidelines | ||
276 | 966 | if content is not None and len(content) > 0: | ||
277 | 967 | guidelines.append({ | ||
278 | 968 | "source": target_name(bugtarget), | ||
279 | 969 | "content": content, | ||
280 | 970 | }) | ||
281 | 971 | # Distribution source packages are shown with both their | ||
282 | 972 | # own reporting guidelines and those of their | ||
283 | 973 | # distribution. | ||
284 | 974 | if IDistributionSourcePackage.providedBy(bugtarget): | ||
285 | 975 | distribution = bugtarget.distribution | ||
286 | 976 | content = distribution.bug_reporting_guidelines | ||
287 | 977 | if content is not None and len(content) > 0: | ||
288 | 978 | guidelines.append({ | ||
289 | 979 | "source": target_name(distribution), | ||
290 | 980 | "content": content, | ||
291 | 981 | }) | ||
292 | 982 | return guidelines | ||
293 | 983 | |||
294 | 984 | def getMainContext(self): | ||
295 | 985 | if IDistributionSourcePackage.providedBy(self.context): | ||
296 | 986 | return self.context.distribution | ||
297 | 987 | else: | ||
298 | 988 | return self.context | ||
299 | 989 | |||
300 | 990 | @cachedproperty | ||
301 | 991 | def is_bug_supervisor(self): | ||
302 | 992 | """ Return True if the logged in user is a bug supervisor.""" | ||
303 | 993 | context = self.getMainContext() | ||
304 | 994 | return BugTask.userHasBugSupervisorPrivilegesContext( | ||
305 | 995 | context, self.user) | ||
306 | 996 | |||
307 | 1020 | 997 | ||
308 | 1021 | class FileBugAdvancedView(FileBugViewBase): | 998 | class FileBugAdvancedView(FileBugViewBase): |
309 | 1022 | """Browser view for filing a bug. | 999 | """Browser view for filing a bug. |
310 | @@ -1131,7 +1108,7 @@ | |||
311 | 1131 | show_summary_in_results = True | 1108 | show_summary_in_results = True |
312 | 1132 | 1109 | ||
313 | 1133 | def initialize(self): | 1110 | def initialize(self): |
315 | 1134 | FilebugShowSimilarBugsView.initialize(self) | 1111 | super(FileBugGuidedView, self).initialize() |
316 | 1135 | if self.redirect_ubuntu_filebug: | 1112 | if self.redirect_ubuntu_filebug: |
317 | 1136 | # The user is trying to file a new Ubuntu bug via the web | 1113 | # The user is trying to file a new Ubuntu bug via the web |
318 | 1137 | # interface and without using apport. Redirect to a page | 1114 | # interface and without using apport. Redirect to a page |
319 | 1138 | 1115 | ||
320 | === modified file 'lib/lp/bugs/browser/configure.zcml' | |||
321 | --- lib/lp/bugs/browser/configure.zcml 2012-07-29 23:38:26 +0000 | |||
322 | +++ lib/lp/bugs/browser/configure.zcml 2012-08-01 01:08:21 +0000 | |||
323 | @@ -103,12 +103,6 @@ | |||
324 | 103 | template="../templates/bugtarget-filebug-inline-form.pt" | 103 | template="../templates/bugtarget-filebug-inline-form.pt" |
325 | 104 | permission="launchpad.AnyPerson"/> | 104 | permission="launchpad.AnyPerson"/> |
326 | 105 | <browser:page | 105 | <browser:page |
327 | 106 | for="lp.bugs.interfaces.bugtarget.IHasBugs" | ||
328 | 107 | class="lp.bugs.browser.bugtarget.FileBugReportingGuidelines" | ||
329 | 108 | template="../templates/bugtarget-filebug-guidelines.pt" | ||
330 | 109 | permission="launchpad.AnyPerson" | ||
331 | 110 | name="+filebug-reporting-guidelines"/> | ||
332 | 111 | <browser:page | ||
333 | 112 | name="+manage-official-tags" | 106 | name="+manage-official-tags" |
334 | 113 | for="lp.bugs.interfaces.bugtarget.IOfficialBugTagTargetRestricted" | 107 | for="lp.bugs.interfaces.bugtarget.IOfficialBugTagTargetRestricted" |
335 | 114 | class="lp.bugs.browser.bugtarget.OfficialBugTagsManageView" | 108 | class="lp.bugs.browser.bugtarget.OfficialBugTagsManageView" |
336 | 115 | 109 | ||
337 | === modified file 'lib/lp/bugs/browser/tests/test_bugtarget_filebug.py' | |||
338 | --- lib/lp/bugs/browser/tests/test_bugtarget_filebug.py 2012-07-26 07:54:40 +0000 | |||
339 | +++ lib/lp/bugs/browser/tests/test_bugtarget_filebug.py 2012-08-01 01:08:21 +0000 | |||
340 | @@ -340,17 +340,11 @@ | |||
341 | 340 | self.assertEqual(0, len(view.errors)) | 340 | self.assertEqual(0, len(view.errors)) |
342 | 341 | self.assertTrue(view.added_bug is not None) | 341 | self.assertTrue(view.added_bug is not None) |
343 | 342 | 342 | ||
344 | 343 | |||
345 | 344 | class TestFileBugReportingGuidelines(TestCaseWithFactory): | ||
346 | 345 | |||
347 | 346 | layer = DatabaseFunctionalLayer | ||
348 | 347 | |||
349 | 348 | def test_filebug_reporting_details(self): | 343 | def test_filebug_reporting_details(self): |
350 | 349 | product = self.factory.makeProduct() | 344 | product = self.factory.makeProduct() |
351 | 350 | login_person(product.owner) | 345 | login_person(product.owner) |
352 | 351 | product.bug_reporting_guidelines = "Include bug details" | 346 | product.bug_reporting_guidelines = "Include bug details" |
355 | 352 | view = create_initialized_view( | 347 | view = create_initialized_view(product, '+filebug') |
354 | 353 | product, '+filebug-reporting-guidelines') | ||
356 | 354 | expected_guidelines = [{ | 348 | expected_guidelines = [{ |
357 | 355 | "source": product.displayname, "content": u"Include bug details", | 349 | "source": product.displayname, "content": u"Include bug details", |
358 | 356 | }] | 350 | }] |
359 | @@ -522,53 +516,6 @@ | |||
360 | 522 | self.assertIn("Thank you for your bug report.", msg) | 516 | self.assertIn("Thank you for your bug report.", msg) |
361 | 523 | 517 | ||
362 | 524 | 518 | ||
363 | 525 | class TestFileBugGuidelinesRequestCache(TestCaseWithFactory): | ||
364 | 526 | # Tests to ensure the request cache contains the expected values for | ||
365 | 527 | # file bug guidelines views. | ||
366 | 528 | |||
367 | 529 | layer = DatabaseFunctionalLayer | ||
368 | 530 | |||
369 | 531 | def _assert_cache_values(self, view, private_bugs, duplicate_search): | ||
370 | 532 | cache = IJSONRequestCache(view.request).objects | ||
371 | 533 | self.assertContentEqual(cache['private_types'], [ | ||
372 | 534 | type.name for type in PRIVATE_INFORMATION_TYPES]) | ||
373 | 535 | self.assertEqual(cache['bug_private_by_default'], private_bugs) | ||
374 | 536 | |||
375 | 537 | def test_product(self): | ||
376 | 538 | project = self.factory.makeProduct(official_malone=True) | ||
377 | 539 | user = self.factory.makePerson() | ||
378 | 540 | login_person(user) | ||
379 | 541 | view = create_initialized_view(project, | ||
380 | 542 | '+filebug-reporting-guidelines', principal=user) | ||
381 | 543 | self._assert_cache_values(view, False, True) | ||
382 | 544 | |||
383 | 545 | def test_product_default_private(self): | ||
384 | 546 | product = self.factory.makeProduct(official_malone=True) | ||
385 | 547 | removeSecurityProxy(product).private_bugs = True | ||
386 | 548 | user = self.factory.makePerson() | ||
387 | 549 | login_person(user) | ||
388 | 550 | view = create_initialized_view(product, | ||
389 | 551 | '+filebug-reporting-guidelines', principal=user) | ||
390 | 552 | self._assert_cache_values(view, True, True) | ||
391 | 553 | |||
392 | 554 | def test_product_no_duplicate_search(self): | ||
393 | 555 | product = self.factory.makeProduct(official_malone=True) | ||
394 | 556 | removeSecurityProxy(product).enable_bugfiling_duplicate_search = False | ||
395 | 557 | user = self.factory.makePerson() | ||
396 | 558 | login_person(user) | ||
397 | 559 | view = create_initialized_view(product, | ||
398 | 560 | '+filebug-reporting-guidelines', principal=user) | ||
399 | 561 | self._assert_cache_values(view, False, False) | ||
400 | 562 | |||
401 | 563 | def test_project_group(self): | ||
402 | 564 | project = self.factory.makeProject() | ||
403 | 565 | user = self.factory.makePerson() | ||
404 | 566 | login_person(user) | ||
405 | 567 | view = create_initialized_view(project, | ||
406 | 568 | '+filebug-reporting-guidelines', principal=user) | ||
407 | 569 | self._assert_cache_values(view, False, True) | ||
408 | 570 | |||
409 | 571 | |||
410 | 572 | class TestFileBugRequestCache(TestCaseWithFactory): | 519 | class TestFileBugRequestCache(TestCaseWithFactory): |
411 | 573 | # Tests to ensure the request cache contains the expected values for | 520 | # Tests to ensure the request cache contains the expected values for |
412 | 574 | # file bug views. | 521 | # file bug views. |
413 | @@ -581,7 +528,7 @@ | |||
414 | 581 | 'disclosure.enhanced_choice_popup.enabled': 'true' | 528 | 'disclosure.enhanced_choice_popup.enabled': 'true' |
415 | 582 | })) | 529 | })) |
416 | 583 | 530 | ||
418 | 584 | def _assert_cache_values(self, view, duplicate_search, private_only=False): | 531 | def _assert_cache_values(self, view, duplicate_search, private_bugs=False): |
419 | 585 | cache = IJSONRequestCache(view.request).objects | 532 | cache = IJSONRequestCache(view.request).objects |
420 | 586 | self.assertEqual( | 533 | self.assertEqual( |
421 | 587 | duplicate_search, cache['enable_bugfiling_duplicate_search']) | 534 | duplicate_search, cache['enable_bugfiling_duplicate_search']) |
422 | @@ -628,6 +575,9 @@ | |||
423 | 628 | bugtask_importance_data.append(new_item) | 575 | bugtask_importance_data.append(new_item) |
424 | 629 | self.assertEqual( | 576 | self.assertEqual( |
425 | 630 | bugtask_importance_data, cache['bugtask_importance_data']) | 577 | bugtask_importance_data, cache['bugtask_importance_data']) |
426 | 578 | self.assertContentEqual(cache['private_types'], [ | ||
427 | 579 | type.name for type in PRIVATE_INFORMATION_TYPES]) | ||
428 | 580 | self.assertEqual(cache['bug_private_by_default'], private_bugs) | ||
429 | 631 | bugtask_info_type_data = [] | 581 | bugtask_info_type_data = [] |
430 | 632 | if not IProjectGroup.providedBy(view.context): | 582 | if not IProjectGroup.providedBy(view.context): |
431 | 633 | for item in view.context.getAllowedBugInformationTypes(): | 583 | for item in view.context.getAllowedBugInformationTypes(): |
432 | 634 | 584 | ||
433 | === removed file 'lib/lp/bugs/templates/bugtarget-filebug-guidelines.pt' | |||
434 | --- lib/lp/bugs/templates/bugtarget-filebug-guidelines.pt 2012-07-05 00:49:00 +0000 | |||
435 | +++ lib/lp/bugs/templates/bugtarget-filebug-guidelines.pt 1970-01-01 00:00:00 +0000 | |||
436 | @@ -1,51 +0,0 @@ | |||
437 | 1 | <tal:root | ||
438 | 2 | xmlns:tal="http://xml.zope.org/namespaces/tal" | ||
439 | 3 | xmlns:metal="http://xml.zope.org/namespaces/metal" | ||
440 | 4 | xmlns:i18n="http://xml.zope.org/namespaces/i18n" | ||
441 | 5 | > | ||
442 | 6 | |||
443 | 7 | <tr id="extra-filebug-details"><td colspan="2" width="100%"><table><tbody> | ||
444 | 8 | <tr> | ||
445 | 9 | <metal:bug_reporting_guidelines | ||
446 | 10 | use-macro="context/@@+filebug-macros/bug_reporting_guidelines" /> | ||
447 | 11 | </tr> | ||
448 | 12 | |||
449 | 13 | <tr tal:define="security_context view/getMainContext"> | ||
450 | 14 | <tal:information_type tal:condition="view/is_bug_supervisor"> | ||
451 | 15 | <td colspan="2" width="100%" | ||
452 | 16 | tal:define="widget nocall: view/widgets/information_type|nothing" | ||
453 | 17 | tal:condition="widget"> | ||
454 | 18 | <label tal:attributes="for widget/name"> | ||
455 | 19 | This bug contains information that is: | ||
456 | 20 | </label> | ||
457 | 21 | <input tal:replace="structure widget" /> | ||
458 | 22 | </td> | ||
459 | 23 | </tal:information_type> | ||
460 | 24 | <tal:security_related tal:condition="not: view/is_bug_supervisor"> | ||
461 | 25 | <td colspan="2" width="100%" | ||
462 | 26 | tal:define="widget nocall: view/widgets/security_related|nothing" | ||
463 | 27 | tal:condition="widget"> | ||
464 | 28 | <table> | ||
465 | 29 | <tbody> | ||
466 | 30 | <tr> | ||
467 | 31 | <td> | ||
468 | 32 | <input type="checkbox" tal:replace="structure widget" /> | ||
469 | 33 | </td> | ||
470 | 34 | <td> | ||
471 | 35 | <label tal:attributes="for widget/name"> | ||
472 | 36 | This bug is a security vulnerability | ||
473 | 37 | </label> | ||
474 | 38 | <div> | ||
475 | 39 | The security group for | ||
476 | 40 | <tal:security-context content="security_context/displayname" /> | ||
477 | 41 | will be notified. | ||
478 | 42 | </div> | ||
479 | 43 | </td> | ||
480 | 44 | </tr> | ||
481 | 45 | </tbody> | ||
482 | 46 | </table> | ||
483 | 47 | </td> | ||
484 | 48 | </tal:security_related> | ||
485 | 49 | </tr> | ||
486 | 50 | </tbody></table></td></tr> | ||
487 | 51 | </tal:root> | ||
488 | 52 | 0 | ||
489 | === modified file 'lib/lp/bugs/templates/bugtarget-macros-filebug.pt' | |||
490 | --- lib/lp/bugs/templates/bugtarget-macros-filebug.pt 2012-06-15 16:23:50 +0000 | |||
491 | +++ lib/lp/bugs/templates/bugtarget-macros-filebug.pt 2012-08-01 01:08:21 +0000 | |||
492 | @@ -57,8 +57,50 @@ | |||
493 | 57 | <metal:row use-macro="context/@@launchpad_form/widget_row" /> | 57 | <metal:row use-macro="context/@@launchpad_form/widget_row" /> |
494 | 58 | </metal:description> | 58 | </metal:description> |
495 | 59 | 59 | ||
498 | 60 | <tr id="extra-filebug-details" | 60 | <tr id="extra-filebug-details"><td colspan="2" width="100%"><table><tbody> |
499 | 61 | tal:replace="structure context/@@+filebug-reporting-guidelines" /> | 61 | <tr> |
500 | 62 | <metal:bug_reporting_guidelines | ||
501 | 63 | use-macro="context/@@+filebug-macros/bug_reporting_guidelines" /> | ||
502 | 64 | </tr> | ||
503 | 65 | |||
504 | 66 | <tr tal:define="security_context view/getMainContext"> | ||
505 | 67 | <tal:information_type tal:condition="view/is_bug_supervisor"> | ||
506 | 68 | <td colspan="2" width="100%" | ||
507 | 69 | tal:define="widget nocall: view/widgets/information_type|nothing" | ||
508 | 70 | tal:condition="widget"> | ||
509 | 71 | <label tal:attributes="for widget/name"> | ||
510 | 72 | This bug contains information that is: | ||
511 | 73 | </label> | ||
512 | 74 | <input tal:replace="structure widget" /> | ||
513 | 75 | </td> | ||
514 | 76 | </tal:information_type> | ||
515 | 77 | <tal:security_related tal:condition="not: view/is_bug_supervisor"> | ||
516 | 78 | <td colspan="2" width="100%" | ||
517 | 79 | tal:define="widget nocall: view/widgets/security_related|nothing" | ||
518 | 80 | tal:condition="widget"> | ||
519 | 81 | <table> | ||
520 | 82 | <tbody> | ||
521 | 83 | <tr> | ||
522 | 84 | <td> | ||
523 | 85 | <input type="checkbox" tal:replace="structure widget" /> | ||
524 | 86 | </td> | ||
525 | 87 | <td> | ||
526 | 88 | <label tal:attributes="for widget/name"> | ||
527 | 89 | This bug is a security vulnerability | ||
528 | 90 | </label> | ||
529 | 91 | <div> | ||
530 | 92 | The security group for | ||
531 | 93 | <tal:security-context content="security_context/displayname" /> | ||
532 | 94 | will be notified. | ||
533 | 95 | </div> | ||
534 | 96 | </td> | ||
535 | 97 | </tr> | ||
536 | 98 | </tbody> | ||
537 | 99 | </table> | ||
538 | 100 | </td> | ||
539 | 101 | </tal:security_related> | ||
540 | 102 | </tr> | ||
541 | 103 | </tbody></table></td></tr> | ||
542 | 62 | 104 | ||
543 | 63 | <tr> | 105 | <tr> |
544 | 64 | <td colspan="2"> | 106 | <td colspan="2"> |
Think I follow. Thanks for the cleanup.