Merge lp:~bac/launchpad/bug-745660 into lp:launchpad

Proposed by Brad Crittenden
Status: Merged
Approved by: Brad Crittenden
Approved revision: no longer in the source branch.
Merged at revision: 12717
Proposed branch: lp:~bac/launchpad/bug-745660
Merge into: lp:launchpad
Diff against target: 764 lines (+145/-518)
5 files modified
.bzrignore (+1/-0)
Makefile (+17/-12)
lib/canonical/launchpad/icing/icon-sprites.positioning (+0/-484)
lib/lp/bugs/browser/structuralsubscription.py (+13/-3)
lib/lp/bugs/browser/tests/test_expose.py (+114/-19)
To merge this branch: bzr merge lp:~bac/launchpad/bug-745660
Reviewer Review Type Date Requested Status
Gavin Panella (community) Approve
Review via email: mp+55636@code.launchpad.net

Commit message

[r=allenap][bug=745660] Filter the list of administered teams shown for structural subscriptions to distributions when a bug supervisor is set.

Description of the change

= Summary =

If a distribution has a bug supervisor team set then only members of
that team my have a structural subscription to that distro. This branch
filters out those teams from the ones presented in the structural
subscription widget.

== Proposed fix ==

The set of teams exposed to JavaScript is filtered under the conditions
stated above.

== Pre-implementation notes ==

Chats with Gary about the problem.

== Implementation details ==

As above.

== Tests ==

bin/test -vvm lp.bugs -t test_expose

== Demo and Q/A ==

Go to https://launchpad.dev/+feature-rules and set the following rule:
malone.advanced-structural-subscriptions.enabled default 1 on

Login as stevea/test.

Go to https://launchpad.dev/ubuntu and click on 'Subscribe to bug mail'.
 Note that 'Ubuntu Gnome Team' is in the list of teams Steve can subscribe.

Go to http://bugs.launchpad.dev/ubuntu and set the Ubuntu Team as the
bug supervisor. You'll note that Ubuntu Gnome Team is not a member of
Ubuntu Team.

Go back to https://launchpad.dev/ubuntu and click on 'Subscribe to bug
mail'. Now you'll see that Ubuntu Gnome Team is not one of his
selections. QED.

= Launchpad lint =

(Will fix as appropriate.)

Checking for conflicts and issues in changed files.

Linting changed files:
  .bzrignore
  lib/lp/bugs/browser/structuralsubscription.py
  lib/lp/bugs/browser/tests/test_expose.py
  Makefile

./lib/lp/bugs/browser/tests/test_expose.py
     111: E231 missing whitespace after ','
./Makefile
      81: Line exceeds 78 characters.
     159: Line exceeds 78 characters.
     289: Line exceeds 78 characters.
     416: Line exceeds 78 characters.
     446: Line exceeds 78 characters.
     480: Line exceeds 78 characters.

To post a comment you must log in.
Revision history for this message
Brad Crittenden (bac) wrote :

This branch also removes icon-sprites.positioning from our tree as it is generated. The Makefile rules are updated to ensure it is built when needed.

Revision history for this message
Gavin Panella (allenap) wrote :

Cool, +1.

[1]

+${ICING}/icon-sprites.positioning: bin/sprite-util
+ ${SHHH} bin/sprite-util create-image
+
+${ICING}/icon-sprites: bin/sprite-util
  ${SHHH} bin/sprite-util create-image

Although make seems to see that the command is identical and only runs
it once, it might be clearer for future maintainers to express it
instead as:

${ICING}/icon-sprites.positioning ${ICING}/icon-sprites: bin/sprite-util
 ${SHHH} bin/sprite-util create-image

[2]

+ def _sort(self, team_info, key='title'):
+ return sorted(team_info, cmp=lambda a,b: cmp(a[key], b[key]))

The cmp argument to sorted it deprecated and is gone in Python 3. This
could be expressed instead as:

        return sorted(team_info, key=lambda item: item[key])

or:

        return sorted(team_info, key=itemgetter(key))

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file '.bzrignore'
--- .bzrignore 2011-03-30 19:42:37 +0000
+++ .bzrignore 2011-03-31 15:37:43 +0000
@@ -80,3 +80,4 @@
80.idea80.idea
81run.gdb81run.gdb
82lib/canonical/launchpad/icing/icon-sprites82lib/canonical/launchpad/icing/icon-sprites
83lib/canonical/launchpad/icing/icon-sprites.positioning
8384
=== modified file 'Makefile'
--- Makefile 2011-03-30 19:42:37 +0000
+++ Makefile 2011-03-31 15:37:43 +0000
@@ -78,7 +78,8 @@
78$(API_INDEX): $(BZR_VERSION_INFO) $(PY)78$(API_INDEX): $(BZR_VERSION_INFO) $(PY)
79 rm -rf $(APIDOC_DIR) $(APIDOC_DIR).tmp79 rm -rf $(APIDOC_DIR) $(APIDOC_DIR).tmp
80 mkdir -p $(APIDOC_DIR).tmp80 mkdir -p $(APIDOC_DIR).tmp
81 LPCONFIG=$(LPCONFIG) $(PY) ./utilities/create-lp-wadl-and-apidoc.py --force "$(WADL_TEMPLATE)"81 LPCONFIG=$(LPCONFIG) $(PY) ./utilities/create-lp-wadl-and-apidoc.py \
82 --force "$(WADL_TEMPLATE)"
82 mv $(APIDOC_DIR).tmp $(APIDOC_DIR)83 mv $(APIDOC_DIR).tmp $(APIDOC_DIR)
8384
84apidoc: compile $(API_INDEX)85apidoc: compile $(API_INDEX)
@@ -156,12 +157,13 @@
156157
157sprite_css: ${LP_BUILT_JS_ROOT}/sprite.css158sprite_css: ${LP_BUILT_JS_ROOT}/sprite.css
158159
159${LP_BUILT_JS_ROOT}/sprite.css: bin/sprite-util ${ICING}/sprite.css.in ${ICING}/icon-sprites.positioning160${LP_BUILT_JS_ROOT}/sprite.css: bin/sprite-util ${ICING}/sprite.css.in \
161 ${ICING}/icon-sprites.positioning
160 ${SHHH} bin/sprite-util create-css162 ${SHHH} bin/sprite-util create-css
161163
162sprite_image: ${ICING}/icon-sprites164sprite_image: ${ICING}/icon-sprites ${ICING}/icon-sprites.positioning
163165
164${ICING}/icon-sprites: bin/sprite-util ${ICING}/icon-sprites.positioning166${ICING}/icon-sprites.positioning ${ICING}/icon-sprites: bin/sprite-util
165 ${SHHH} bin/sprite-util create-image167 ${SHHH} bin/sprite-util create-image
166168
167# We absolutely do not want to include the lazr.testing module and169# We absolutely do not want to include the lazr.testing module and
@@ -410,7 +412,9 @@
410 /var/tmp/testkeyserver412 /var/tmp/testkeyserver
411 # /var/tmp/launchpad_mailqueue is created read-only on ec2test413 # /var/tmp/launchpad_mailqueue is created read-only on ec2test
412 # instances.414 # instances.
413 if [ -w /var/tmp/launchpad_mailqueue ]; then $(RM) -rf /var/tmp/launchpad_mailqueue; fi415 if [ -w /var/tmp/launchpad_mailqueue ]; then \
416 $(RM) -rf /var/tmp/launchpad_mailqueue; \
417 fi
414418
415419
416realclean: clean420realclean: clean
@@ -474,10 +478,11 @@
474 --docformat restructuredtext --verbose-about epytext-summary \478 --docformat restructuredtext --verbose-about epytext-summary \
475 $(PYDOCTOR_OPTIONS)479 $(PYDOCTOR_OPTIONS)
476480
477.PHONY: apidoc buildout_bin check doc tags TAGS zcmldocs realclean clean debug \481.PHONY: apidoc buildout_bin check doc tags TAGS zcmldocs realclean \
478 stop start run ftest_build ftest_inplace test_build test_inplace \482 clean debug stop start run ftest_build ftest_inplace \
479 pagetests check schema default launchpad.pot pull_branches \483 test_build test_inplace pagetests check schema default \
480 scan_branches sync_branches reload-apache hosted_branches \484 launchpad.pot pull_branches scan_branches sync_branches \
481 check_mailman check_config jsbuild jsbuild_lazr clean_js \485 reload-apache hosted_branches check_mailman check_config \
482 clean_buildout buildonce_eggs build_eggs sprite_css sprite_image \486 jsbuild jsbuild_lazr clean_js clean_buildout buildonce_eggs \
483 css_combine compile check_schema pydoctor clean_logs \487 build_eggs sprite_css sprite_image css_combine compile \
488 check_schema pydoctor clean_logs
484489
=== removed file 'lib/canonical/launchpad/icing/icon-sprites.positioning'
--- lib/canonical/launchpad/icing/icon-sprites.positioning 2011-03-22 05:56:34 +0000
+++ lib/canonical/launchpad/icing/icon-sprites.positioning 1970-01-01 00:00:00 +0000
@@ -1,484 +0,0 @@
1/* DO NOT EDIT THIS FILE BY HAND!!! */
2/* It is autogenerated by spriteutils. */
3{
4 "../images/arrowLeft.png": [
5 0,
6 -14918
7 ],
8 "../images/cancel.png": [
9 0,
10 -7540
11 ],
12 "../images/milestone.png": [
13 0,
14 -3440
15 ],
16 "../images/build-needed.png": [
17 0,
18 -13442
19 ],
20 "../images/team.png": [
21 0,
22 -2130
23 ],
24 "../images/bug-undecided.png": [
25 0,
26 -8036
27 ],
28 "../images/blueprint-low.png": [
29 0,
30 -5900
31 ],
32 "../images/meeting.png": [
33 0,
34 -10490
35 ],
36 "../images/no.png": [
37 0,
38 -1312
39 ],
40 "../images/distribution-badge.png": [
41 0,
42 -9184
43 ],
44 "../images/arrowTop.png": [
45 0,
46 -14590
47 ],
48 "../images/zoom-in.png": [
49 0,
50 -11802
51 ],
52 "../images/team-badge.png": [
53 0,
54 -2294
55 ],
56 "../images/blue-bar.png": [
57 0,
58 -15082
59 ],
60 "../images/arrowStart.png": [
61 0,
62 -14262
63 ],
64 "../images/ppa-icon-inactive.png": [
65 0,
66 -12458
67 ],
68 "../images/zoom-out.png": [
69 0,
70 -11966
71 ],
72 "../images/purple-bar.png": [
73 0,
74 -15410
75 ],
76 "../images/bullet.png": [
77 0,
78 -11638
79 ],
80 "../images/info-large.png": [
81 0,
82 -17504
83 ],
84 "../images/trash-logo.png": [
85 0,
86 -20340
87 ],
88 "../images/warning.png": [
89 0,
90 -10162
91 ],
92 "../images/mail.png": [
93 0,
94 -3932
95 ],
96 "../images/build-failure.png": [
97 0,
98 -13606
99 ],
100 "../images/branch-large.png": [
101 0,
102 -16230
103 ],
104 "../images/download-large.png": [
105 0,
106 -17322
107 ],
108 "../images/private-large.png": [
109 0,
110 -18232
111 ],
112 "../images/launchpad-large.png": [
113 0,
114 -17686
115 ],
116 "../images/translation-file.png": [
117 0,
118 -10818
119 ],
120 "../images/source-package-recipe.png": [
121 0,
122 -12622
123 ],
124 "../images/project-logo.png": [
125 0,
126 -18842
127 ],
128 "../images/bug-medium.png": [
129 0,
130 -4752
131 ],
132 "../images/architecture.png": [
133 0,
134 -12130
135 ],
136 "../images/tour-icon": [
137 0,
138 -16066
139 ],
140 "../images/trash-icon.png": [
141 0,
142 -11146
143 ],
144 "../images/person-inactive.png": [
145 0,
146 -6722
147 ],
148 "../images/arrowBottom.png": [
149 0,
150 -14754
151 ],
152 "../images/project.png": [
153 0,
154 -9508
155 ],
156 "../images/crowd.png": [
157 0,
158 -1640
159 ],
160 "../images/info.png": [
161 0,
162 -492
163 ],
164 "../images/flame-icon.png": [
165 0,
166 -7872
167 ],
168 "../images/ubuntu-icon.png": [
169 0,
170 -6556
171 ],
172 "../images/link.png": [
173 0,
174 -3768
175 ],
176 "../images/person-logo.png": [
177 0,
178 -19270
179 ],
180 "../images/distribution-logo.png": [
181 0,
182 -18628
183 ],
184 "../images/retry.png": [
185 0,
186 -9020
187 ],
188 "../images/rss.png": [
189 0,
190 -6392
191 ],
192 "../images/private.png": [
193 0,
194 -10326
195 ],
196 "../images/merge-proposal-icon.png": [
197 0,
198 -12950
199 ],
200 "../images/download.png": [
201 0,
202 -984
203 ],
204 "../images/arrowDown.png": [
205 0,
206 -14098
207 ],
208 "../images/package-binary.png": [
209 0,
210 -8856
211 ],
212 "../images/maybe.png": [
213 0,
214 -7212
215 ],
216 "../images/bug-status-expand.png": [
217 0,
218 -12786
219 ],
220 "../images/crowd-large.png": [
221 0,
222 -16594
223 ],
224 "../images/blueprint.png": [
225 0,
226 -5244
227 ],
228 "../images/project-badge.png": [
229 0,
230 -9346
231 ],
232 "../images/bug-high.png": [
233 0,
234 -4588
235 ],
236 "../images/blueprint-undefined.png": [
237 0,
238 -6064
239 ],
240 "../images/blueprint-not.png": [
241 0,
242 -6228
243 ],
244 "../images/stop.png": [
245 0,
246 -11310
247 ],
248 "../images/flame-large.png": [
249 0,
250 -17140
251 ],
252 "../images/bug-dupe-icon.png": [
253 0,
254 -8528
255 ],
256 "../images/bug-critical.png": [
257 0,
258 -4424
259 ],
260 "../images/build-success.png": [
261 0,
262 -13278
263 ],
264 "../images/haspatch-icon.png": [
265 0,
266 -15902
267 ],
268 "../images/person-inactive-badge.png": [
269 0,
270 -6886
271 ],
272 "../images/ppa-icon.png": [
273 0,
274 -12294
275 ],
276 "../images/yes.png": [
277 0,
278 -1476
279 ],
280 "../images/team-logo.png": [
281 0,
282 -19698
283 ],
284 "../images/arrowRight.png": [
285 0,
286 -2456
287 ],
288 "../images/blueprint-high.png": [
289 0,
290 -5572
291 ],
292 "../images/product.png": [
293 0,
294 -9834
295 ],
296 "../images/bug-low.png": [
297 0,
298 -4916
299 ],
300 "../images/package-source.png": [
301 0,
302 -3276
303 ],
304 "../images/language.png": [
305 0,
306 -3604
307 ],
308 "../images/person.png": [
309 0,
310 -1804
311 ],
312 "../images/arrowUp.png": [
313 0,
314 -13934
315 ],
316 "../images/distribution.png": [
317 0,
318 -3112
319 ],
320 "../images/error-large.png": [
321 0,
322 -16958
323 ],
324 "../images/news.png": [
325 0,
326 -15738
327 ],
328 "../images/treeExpanded.png": [
329 0,
330 -2784
331 ],
332 "../images/build-depwait.png": [
333 0,
334 -13770
335 ],
336 "../images/blueprint-essential.png": [
337 0,
338 -5408
339 ],
340 "../images/question.png": [
341 0,
342 -656
343 ],
344 "../images/error.png": [
345 0,
346 -7376
347 ],
348 "../images/bug-unknown.png": [
349 0,
350 -8364
351 ],
352 "../images/product-logo.png": [
353 0,
354 -19056
355 ],
356 "../images/blueprint-medium.png": [
357 0,
358 -5736
359 ],
360 "../images/product-badge.png": [
361 0,
362 -9672
363 ],
364 "../images/list.png": [
365 0,
366 -11474
367 ],
368 "../images/launchpad-logo.png": [
369 0,
370 -18414
371 ],
372 "../images/flame-logo.png": [
373 0,
374 -20126
375 ],
376 "../images/translation-template.png": [
377 0,
378 -10982
379 ],
380 "../images/bugtracker-icon.png": [
381 0,
382 -8692
383 ],
384 "../images/meeting-logo.png": [
385 0,
386 -19912
387 ],
388 "../images/treeCollapsed.png": [
389 0,
390 -2620
391 ],
392 "../images/green-bar.png": [
393 0,
394 -15246
395 ],
396 "../images/build-superseded.png": [
397 0,
398 -13114
399 ],
400 "../images/trash-large.png": [
401 0,
402 -18050
403 ],
404 "../images/red-bar.png": [
405 0,
406 -15574
407 ],
408 "../images/add.png": [
409 0,
410 0
411 ],
412 "../images/remove.png": [
413 0,
414 -328
415 ],
416 "../images/read-only.png": [
417 0,
418 -9998
419 ],
420 "../images/person-inactive-logo.png": [
421 0,
422 -19484
423 ],
424 "../images/edit.png": [
425 0,
426 -164
427 ],
428 "../images/bug-wishlist.png": [
429 0,
430 -5080
431 ],
432 "../images/warning-large.png": [
433 0,
434 -16412
435 ],
436 "../images/arrowEnd.png": [
437 0,
438 -14426
439 ],
440 "../images/cve.png": [
441 0,
442 -4096
443 ],
444 "../images/notification-close.png": [
445 0,
446 -20725
447 ],
448 "../images/merge-proposal-large.png": [
449 0,
450 -17868
451 ],
452 "../images/branch.png": [
453 0,
454 -2948
455 ],
456 "../images/person-badge.png": [
457 0,
458 -1968
459 ],
460 "../images/notification-private.png": [
461 0,
462 -20554
463 ],
464 "../images/bug.png": [
465 0,
466 -4260
467 ],
468 "../images/bug-remote.png": [
469 0,
470 -8200
471 ],
472 "../images/translation.png": [
473 0,
474 -10654
475 ],
476 "../images/confirm.png": [
477 0,
478 -7706
479 ],
480 "../images/search.png": [
481 0,
482 -1148
483 ]
484}
485\ No newline at end of file0\ No newline at end of file
4861
=== modified file 'lib/lp/bugs/browser/structuralsubscription.py'
--- lib/lp/bugs/browser/structuralsubscription.py 2011-03-29 22:34:04 +0000
+++ lib/lp/bugs/browser/structuralsubscription.py 2011-03-31 15:37:43 +0000
@@ -58,6 +58,9 @@
58 IStructuralSubscriptionForm,58 IStructuralSubscriptionForm,
59 IStructuralSubscriptionTarget,59 IStructuralSubscriptionTarget,
60 )60 )
61from lp.registry.interfaces.distribution import (
62 IDistribution,
63 )
61from lp.registry.interfaces.distributionsourcepackage import (64from lp.registry.interfaces.distributionsourcepackage import (
62 IDistributionSourcePackage,65 IDistributionSourcePackage,
63 )66 )
@@ -376,7 +379,7 @@
376def expose_structural_subscription_data_to_js(context, request,379def expose_structural_subscription_data_to_js(context, request,
377 user, subscriptions=None):380 user, subscriptions=None):
378 """Expose all of the data for a structural subscription to JavaScript."""381 """Expose all of the data for a structural subscription to JavaScript."""
379 expose_user_administered_teams_to_js(request, user)382 expose_user_administered_teams_to_js(request, user, context)
380 expose_enum_to_js(request, BugTaskImportance, 'importances')383 expose_enum_to_js(request, BugTaskImportance, 'importances')
381 expose_enum_to_js(request, BugTaskStatus, 'statuses')384 expose_enum_to_js(request, BugTaskStatus, 'statuses')
382 if subscriptions is None:385 if subscriptions is None:
@@ -393,13 +396,20 @@
393 IJSONRequestCache(request).objects[name] = info396 IJSONRequestCache(request).objects[name] = info
394397
395398
396def expose_user_administered_teams_to_js(request, user,399def expose_user_administered_teams_to_js(request, user, context,
397 absoluteURL=absoluteURL):400 absoluteURL=absoluteURL):
398 """Make the list of teams the user adminsters available to JavaScript."""401 """Make the list of teams the user administers available to JavaScript."""
399 info = []402 info = []
400 api_request = IWebServiceClientRequest(request)403 api_request = IWebServiceClientRequest(request)
404 is_distro = IDistribution.providedBy(context)
401 if user is not None:405 if user is not None:
402 for team in user.getAdministratedTeams():406 for team in user.getAdministratedTeams():
407 # If the context is a distro AND a bug supervisor is set AND
408 # the admininistered team is not a member of the bug supervisor
409 # team THEN skip it.
410 if (is_distro and context.bug_supervisor is not None and
411 not team.inTeam(context.bug_supervisor)):
412 continue
403 info.append({413 info.append({
404 'link': absoluteURL(team, api_request),414 'link': absoluteURL(team, api_request),
405 'title': team.title,415 'title': team.title,
406416
=== modified file 'lib/lp/bugs/browser/tests/test_expose.py'
--- lib/lp/bugs/browser/tests/test_expose.py 2011-03-24 15:31:53 +0000
+++ lib/lp/bugs/browser/tests/test_expose.py 2011-03-31 15:37:43 +0000
@@ -3,6 +3,8 @@
33
4"""Tests for helpers that expose data about a user to on-page JavaScript."""4"""Tests for helpers that expose data about a user to on-page JavaScript."""
55
6from operator import itemgetter
7
6from lazr.enum import (8from lazr.enum import (
7 DBEnumeratedType,9 DBEnumeratedType,
8 DBItem,10 DBItem,
@@ -86,33 +88,126 @@
86 return self.return_value88 return self.return_value
8789
8890
89class TestStructuralSubscriptionHelpers(TestCase):91class TestExposeAdministeredTeams(TestCaseWithFactory):
90 """Test the helpers used to add data that the on-page JS can use."""92 """Test the function to expose administered team."""
9193
92 def test_teams(self):94 layer = DatabaseFunctionalLayer
95
96 def setUp(self):
97 super(TestExposeAdministeredTeams, self).setUp()
98 self.request = FakeRequest()
99 self.user = self.factory.makePerson()
100
101 def _setup_teams(self, owner):
102 self.bug_super_team = self.factory.makeTeam(
103 name='bug-supervisor-team', owner=owner)
104 bug_super_subteam = self.factory.makeTeam(
105 name='bug-supervisor-sub-team', owner=owner)
106 self.factory.makeTeam(
107 name='unrelated-team', owner=owner)
108 with person_logged_in(owner):
109 bug_super_subteam.join(
110 self.bug_super_team, self.bug_super_team.teamowner)
111
112 def _sort(self, team_info, key='title'):
113 return sorted(team_info, key=itemgetter(key))
114
115 def test_teams_for_non_distro(self):
93 # The expose_user_administered_teams_to_js function loads some data116 # The expose_user_administered_teams_to_js function loads some data
94 # about the teams the requesting user administers into the response to117 # about the teams the requesting user administers into the response to
95 # be made available to JavaScript.118 # be made available to JavaScript.
96119
97 request = FakeRequest()120 context = self.factory.makeProduct(owner=self.user)
98 user = FakeUser()121 self._setup_teams(self.user)
99 expose_user_administered_teams_to_js(request, user,122
123 expose_user_administered_teams_to_js(self.request, self.user, context,
100 absoluteURL=fake_absoluteURL)124 absoluteURL=fake_absoluteURL)
101125
102 # The team information should have been added to the request.126 # The team information should have been added to the request.
103 self.assertThat(request.objects, Contains('administratedTeams'))127 self.assertThat(self.request.objects, Contains('administratedTeams'))
104 team_info = request.objects['administratedTeams']128 team_info = self._sort(self.request.objects['administratedTeams'])
105 # Since there are two (fake) teams, there should be two items in the129 # Since there are three teams, there should be three items in the
106 # list of team info.130 # list of team info.
107 self.assertThat(len(team_info), Equals(2))131 expected_number_teams = 3
108 # The items info consist of a dictionary with link and title keys.132 self.assertThat(len(team_info), Equals(expected_number_teams))
109 self.assertThat(team_info[0], KeysEqual('link', 'title'))133 # The items info consist of a dictionary with link and title keys.
110 self.assertThat(team_info[1], KeysEqual('link', 'title'))134 for i in range(expected_number_teams):
111 # The link is the title of the team.135 self.assertThat(team_info[i], KeysEqual('link', 'title'))
112 self.assertThat(team_info[0]['title'], Equals('Team One'))136 # The link is the title of the team.
113 # The link is the API link to the team.137 self.assertThat(
114 self.assertThat(team_info[0]['link'],138 team_info[0]['title'], Equals(u'Bug Supervisor Sub Team'))
115 Equals('http://example.com/TeamOne'))139 self.assertThat(
140 team_info[1]['title'], Equals(u'Bug Supervisor Team'))
141 self.assertThat(
142 team_info[2]['title'], Equals(u'Unrelated Team'))
143 # The link is the API link to the team.
144 self.assertThat(team_info[0]['link'],
145 Equals('http://example.com/BugSupervisorSubTeam'))
146
147 def test_teams_for_distro_with_bug_super(self):
148 self._setup_teams(self.user)
149 context = self.factory.makeDistribution(
150 owner=self.user, members=self.bug_super_team)
151 with person_logged_in(self.user):
152 context.setBugSupervisor(
153 self.bug_super_team, self.user)
154
155 expose_user_administered_teams_to_js(self.request, self.user, context,
156 absoluteURL=fake_absoluteURL)
157
158 # The team information should have been added to the request.
159 self.assertThat(self.request.objects, Contains('administratedTeams'))
160 team_info = self._sort(self.request.objects['administratedTeams'])
161
162 # Since the distro only returns teams that are members of the bug
163 # supervisor team, we only expect two.
164 expected_number_teams = 2
165 self.assertThat(len(team_info), Equals(expected_number_teams))
166 # The items info consist of a dictionary with link and title keys.
167 for i in range(expected_number_teams):
168 self.assertThat(team_info[i], KeysEqual('link', 'title'))
169 # The link is the title of the team.
170 self.assertThat(
171 team_info[0]['title'], Equals(u'Bug Supervisor Sub Team'))
172 self.assertThat(
173 team_info[1]['title'], Equals(u'Bug Supervisor Team'))
174 # The link is the API link to the team.
175 self.assertThat(team_info[0]['link'],
176 Equals('http://example.com/BugSupervisorSubTeam'))
177
178 def test_teams_for_distro_with_no_bug_super(self):
179 self._setup_teams(self.user)
180 context = self.factory.makeDistribution(
181 owner=self.user, members=self.bug_super_team)
182
183 expose_user_administered_teams_to_js(self.request, self.user, context,
184 absoluteURL=fake_absoluteURL)
185
186 # The team information should have been added to the request.
187 self.assertThat(self.request.objects, Contains('administratedTeams'))
188 team_info = self._sort(self.request.objects['administratedTeams'])
189
190 # Since the distro has no bug supervisor set, all administered teams
191 # are returned.
192 expected_number_teams = 3
193 self.assertThat(len(team_info), Equals(expected_number_teams))
194 # The items info consist of a dictionary with link and title keys.
195 for i in range(expected_number_teams):
196 self.assertThat(team_info[i], KeysEqual('link', 'title'))
197 # The link is the title of the team.
198 self.assertThat(
199 team_info[0]['title'], Equals(u'Bug Supervisor Sub Team'))
200 self.assertThat(
201 team_info[1]['title'], Equals(u'Bug Supervisor Team'))
202 self.assertThat(
203 team_info[2]['title'], Equals(u'Unrelated Team'))
204 # The link is the API link to the team.
205 self.assertThat(team_info[0]['link'],
206 Equals('http://example.com/BugSupervisorSubTeam'))
207
208
209class TestStructuralSubscriptionHelpers(TestCase):
210 """Test the helpers used to add data that the on-page JS can use."""
116211
117 def test_expose_enum_to_js(self):212 def test_expose_enum_to_js(self):
118 # Loads the titles of an enum into the response.213 # Loads the titles of an enum into the response.