Merge lp:~jkakar/kanban/optional-needs-testing into lp:kanban

Proposed by Jamu Kakar
Status: Merged
Approved by: Martin Pool
Approved revision: 28
Merged at revision: 24
Proposed branch: lp:~jkakar/kanban/optional-needs-testing
Merge into: lp:kanban
Diff against target: 555 lines (+246/-39)
6 files modified
kanban/board.py (+28/-8)
kanban/commands.py (+14/-6)
kanban/templates/kanban.html (+88/-2)
kanban/tests/test_board.py (+35/-16)
media/decogrids-10.css (+74/-0)
media/decogrids-12.css (+7/-7)
To merge this branch: bzr merge lp:~jkakar/kanban/optional-needs-testing
Reviewer Review Type Date Requested Status
Martin Pool Approve
Review via email: mp+53119@code.launchpad.net

Description of the change

This branch introduces the following changes:

- The 'generate-milestone-kanban' and 'generate-person-kanban'
  commands both take an optional --include-needs-testing argument.
  The 'Needs testing' category is disabled by default, and only
  displayed when this argument is provided.

- A new 10-column grid CSS file is available, and is used when the
  'Needs testing' category is disabled.

To post a comment you must log in.
28. By Jamu Kakar

- Improved help text when 'Needs testing' is disabled.

Revision history for this message
Martin Pool (mbp) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'kanban/board.py'
--- kanban/board.py 2011-02-17 10:07:00 +0000
+++ kanban/board.py 2011-03-12 20:16:43 +0000
@@ -126,10 +126,16 @@
126126
127127
128class BugCollectionMixin(object):128class BugCollectionMixin(object):
129 """A named collecton of L{Bug}s organized into categories."""129 """A named collecton of L{Bug}s organized into categories.
130130
131 def __init__(self, name):131 @param name: The name of the L{Bug} collection.
132 @param include_needs_testing: Optionally, a flag indicating whether or not
133 to use the 'Needs testing' category. Defaults to C{False}.
134 """
135
136 def __init__(self, name, include_needs_testing=False):
132 self.name = name137 self.name = name
138 self.include_needs_testing = include_needs_testing
133 self.bugs = []139 self.bugs = []
134 self.queued = []140 self.queued = []
135 self.in_progress = []141 self.in_progress = []
@@ -146,7 +152,10 @@
146 elif bug.needs_release():152 elif bug.needs_release():
147 self.needs_release.append(bug)153 self.needs_release.append(bug)
148 elif bug.needs_testing():154 elif bug.needs_testing():
149 self.needs_testing.append(bug)155 if self.include_needs_testing:
156 self.needs_testing.append(bug)
157 else:
158 self.needs_release.append(bug)
150 elif bug.needs_review():159 elif bug.needs_review():
151 self.needs_review.append(bug)160 self.needs_review.append(bug)
152 elif bug.in_progress():161 elif bug.in_progress():
@@ -159,6 +168,8 @@
159 """A story is a collection of L{Bug}s related to a particular feature.168 """A story is a collection of L{Bug}s related to a particular feature.
160169
161 @param name: The name of this story.170 @param name: The name of this story.
171 @param include_needs_testing: Optionally, a flag indicating whether or not
172 to use the 'Needs testing' category. Defaults to C{False}.
162 """173 """
163174
164175
@@ -166,10 +177,13 @@
166 """A collection of L{Bug}s grouped into L{Story}s.177 """A collection of L{Bug}s grouped into L{Story}s.
167178
168 @param name: The name of this collection.179 @param name: The name of this collection.
180 @param include_needs_testing: Optionally, a flag indicating whether or not
181 to use the 'Needs testing' category. Defaults to C{False}.
169 """182 """
170183
171 def __init__(self, name):184 def __init__(self, name, include_needs_testing=None):
172 super(StoryCollectionMixin, self).__init__(name)185 super(StoryCollectionMixin, self).__init__(
186 name, include_needs_testing=include_needs_testing)
173 self._stories = {}187 self._stories = {}
174188
175 @property189 @property
@@ -213,10 +227,14 @@
213 @param project_name: The name of the project or project group in Launchpad227 @param project_name: The name of the project or project group in Launchpad
214 this milestone is part of.228 this milestone is part of.
215 @param milestone_name: The name of this milestone.229 @param milestone_name: The name of this milestone.
230 @param include_needs_testing: Optionally, a flag indicating whether or not
231 to use the 'Needs testing' category. Defaults to C{False}.
216 """232 """
217233
218 def __init__(self, project_name, milestone_name):234 def __init__(self, project_name, milestone_name,
219 super(MilestoneBoard, self).__init__(milestone_name)235 include_needs_testing=None):
236 super(MilestoneBoard, self).__init__(
237 milestone_name, include_needs_testing=include_needs_testing)
220 self.project_name = project_name238 self.project_name = project_name
221239
222240
@@ -226,6 +244,8 @@
226 person or team.244 person or team.
227245
228 @param name: The name of the person or team.246 @param name: The name of the person or team.
247 @param include_needs_testing: Optionally, a flag indicating whether or not
248 to use the 'Needs testing' category. Defaults to C{False}.
229 """249 """
230250
231251
232252
=== modified file 'kanban/commands.py'
--- kanban/commands.py 2011-02-17 10:07:00 +0000
+++ kanban/commands.py 2011-03-12 20:16:43 +0000
@@ -57,12 +57,15 @@
5757
58 takes_args = ["person_name"]58 takes_args = ["person_name"]
59 takes_options = [Option("output-file", short_name="o", type=str,59 takes_options = [Option("output-file", short_name="o", type=str,
60 help="Write HTML to file.")]60 help="Write HTML to file."),
61 Option("include-needs-testing",
62 help="Include the 'Needs testing' category.")]
61 _see_also = ["launchpad-login"]63 _see_also = ["launchpad-login"]
6264
63 def run(self, person_name, output_file=None):65 def run(self, person_name, output_file=None, include_needs_testing=None):
64 launchpad = get_launchpad()66 launchpad = get_launchpad()
65 person_board = PersonBoard(person_name)67 person_board = PersonBoard(person_name,
68 include_needs_testing=include_needs_testing)
66 bugs = get_person_assigned_bugs(launchpad, person_name)69 bugs = get_person_assigned_bugs(launchpad, person_name)
67 for bug in sorted(bugs, compare_bugs):70 for bug in sorted(bugs, compare_bugs):
68 person_board.add(bug)71 person_board.add(bug)
@@ -74,12 +77,17 @@
7477
75 takes_args = ["project_group", "milestone_name"]78 takes_args = ["project_group", "milestone_name"]
76 takes_options = [Option("output-file", short_name="o", type=str,79 takes_options = [Option("output-file", short_name="o", type=str,
77 help="Write HTML to file.")]80 help="Write HTML to file."),
81 Option("include-needs-testing",
82 help="Include the 'Needs testing' category.")]
78 _see_also = ["launchpad-login"]83 _see_also = ["launchpad-login"]
7984
80 def run(self, project_group, milestone_name, output_file=None):85 def run(self, project_group, milestone_name, output_file=None,
86 include_needs_testing=None):
81 launchpad = get_launchpad()87 launchpad = get_launchpad()
82 milestone_board = MilestoneBoard(project_group, milestone_name)88 milestone_board = MilestoneBoard(
89 project_group, milestone_name,
90 include_needs_testing=include_needs_testing)
83 bugs = get_milestone_bugs(launchpad, project_group, milestone_name)91 bugs = get_milestone_bugs(launchpad, project_group, milestone_name)
84 for bug in sorted(bugs, compare_bugs):92 for bug in sorted(bugs, compare_bugs):
85 milestone_board.add(bug)93 milestone_board.add(bug)
8694
=== modified file 'kanban/templates/kanban.html'
--- kanban/templates/kanban.html 2011-02-17 10:07:00 +0000
+++ kanban/templates/kanban.html 2011-03-12 20:16:43 +0000
@@ -1,14 +1,22 @@
1<html>1<html>
2 <head>2 <head>
3 <title>{{ kanban_board.project_name }} {{ kanban_board.name }}</title>3 <title>{{ kanban_board.project_name }} {{ kanban_board.name }}</title>
4 {% if kanban_board.include_needs_testing %}
4 <link rel="stylesheet" type="text/css" href="media/decogrids-12.css" />5 <link rel="stylesheet" type="text/css" href="media/decogrids-12.css" />
6 {% else %}
7 <link rel="stylesheet" type="text/css" href="media/decogrids-10.css" />
8 {% endif %}
5 <link rel="stylesheet" type="text/css" href="media/kanban.css" />9 <link rel="stylesheet" type="text/css" href="media/kanban.css" />
6 </head>10 </head>
711
8 <body>12 <body>
9 <div id="container">13 <div id="container">
10 <div id="heading" class="row">14 <div id="heading" class="row">
15 {% if kanban_board.include_needs_testing %}
11 <div class="position-0 width-12 cell">16 <div class="position-0 width-12 cell">
17 {% else %}
18 <div class="position-0 width-10 cell">
19 {% endif %}
12 {% if is_milestone %}20 {% if is_milestone %}
13 <h1><a href="https://launchpad.net/{{ kanban_board.project_name }}">{{ kanban_board.project_name }}</a> <a href="https://launchpad.net/{{ kanban_board.project_name }}/+milestone/{{ kanban_board.name}}">{{ kanban_board.name }}</a> <span class="bug-count">{{ kanban_board.bugs|length }} bugs</span></h1>21 <h1><a href="https://launchpad.net/{{ kanban_board.project_name }}">{{ kanban_board.project_name }}</a> <a href="https://launchpad.net/{{ kanban_board.project_name }}/+milestone/{{ kanban_board.name}}">{{ kanban_board.name }}</a> <span class="bug-count">{{ kanban_board.bugs|length }} bugs</span></h1>
14 {% else %}22 {% else %}
@@ -21,17 +29,30 @@
21 <div class="position-0 width-2 cell"><h2>Queued <span class="bug-count">{{ kanban_board.queued|length }} bugs</span></h2></div>29 <div class="position-0 width-2 cell"><h2>Queued <span class="bug-count">{{ kanban_board.queued|length }} bugs</span></h2></div>
22 <div class="position-2 width-2 cell"><h2>In progress <span class="bug-count">{{ kanban_board.in_progress|length }} bugs</span></h2></div>30 <div class="position-2 width-2 cell"><h2>In progress <span class="bug-count">{{ kanban_board.in_progress|length }} bugs</span></h2></div>
23 <div class="position-4 width-2 cell"><h2>Needs review <span class="bug-count">{{ kanban_board.needs_review|length }} bugs</span></h2></div>31 <div class="position-4 width-2 cell"><h2>Needs review <span class="bug-count">{{ kanban_board.needs_review|length }} bugs</span></h2></div>
32 {% if kanban_board.include_needs_testing %}
24 <div class="position-6 width-2 cell"><h2>Needs testing <span class="bug-count">{{ kanban_board.needs_testing|length }} bugs</span></h2></div>33 <div class="position-6 width-2 cell"><h2>Needs testing <span class="bug-count">{{ kanban_board.needs_testing|length }} bugs</span></h2></div>
25 <div class="position-8 width-2 cell"><h2>Needs release <span class="bug-count">{{ kanban_board.needs_release|length }} bugs</span></h2></div>34 <div class="position-8 width-2 cell"><h2>Needs release <span class="bug-count">{{ kanban_board.needs_release|length }} bugs</span></h2></div>
26 <div class="position-10 width-2 cell"><h2>Released <span class="bug-count">{{ kanban_board.released|length }} bugs</span></h2></div>35 <div class="position-10 width-2 cell"><h2>Released <span class="bug-count">{{ kanban_board.released|length }} bugs</span></h2></div>
36 {% else %}
37 <div class="position-6 width-2 cell"><h2>Needs release <span class="bug-count">{{ kanban_board.needs_release|length }} bugs</span></h2></div>
38 <div class="position-8 width-2 cell"><h2>Released <span class="bug-count">{{ kanban_board.released|length }} bugs</span></h2></div>
39 {% endif %}
27 </div>40 </div>
2841
29 {% for story in kanban_board.stories %}42 {% for story in kanban_board.stories %}
30 <div class="tiles row story">43 <div class="tiles row story">
31 {% if story.name %}44 {% if story.name %}
32 <div class="position-0 width-12 cell">{{ story.name }}</div>45 {% if kanban_board.include_needs_testing %}
46 <div class="position-0 width-12 cell">{{ story.name }}</div>
47 {% else %}
48 <div class="position-0 width-10 cell">{{ story.name }}</div>
49 {% endif %}
33 {% else %}50 {% else %}
34 <div class="position-0 width-12 cell">uncategorized</div>51 {% if kanban_board.include_needs_testing %}
52 <div class="position-0 width-12 cell">uncategorized</div>
53 {% else %}
54 <div class="position-0 width-10 cell">uncategorized</div>
55 {% endif %}
35 {% endif %}56 {% endif %}
36 </div>57 </div>
3758
@@ -115,6 +136,7 @@
115136
116 </div>137 </div>
117138
139 {% if kanban_board.include_needs_testing %}
118 <div class="position-6 width-2 cell">140 <div class="position-6 width-2 cell">
119141
120 {% for bug in story.needs_testing %}142 {% for bug in story.needs_testing %}
@@ -171,6 +193,45 @@
171 {% endfor %}193 {% endfor %}
172194
173 </div>195 </div>
196 {% else %}
197 <div class="position-6 width-2 cell">
198
199 {% for bug in story.needs_release %}
200 <div class="tile">
201 {% if bug.assignee %}
202 <span class="assignee">{{ bug.assignee }}</span>
203 {% endif %}
204 <a href="https://bugs.launchpad.net/bugs/{{ bug.id }}">#{{ bug.id }}</a> <span class="{{ bug.importance|importance_css_class }}">{{ bug.importance }}</span>
205 <br/>
206 <div class="project">{{ bug.project }}</div>
207 <div>{{ bug.title }}</div>
208 {% if bug.branch %}
209 <div class="merge-proposal"><a href="{{ bug|branch_url }}">{{ bug.branch|branch_name }}</a></div>
210 {% endif %}
211 </div>
212 {% endfor %}
213
214 </div>
215
216 <div class="position-8 width-2 cell">
217
218 {% for bug in story.released %}
219 <div class="tile">
220 {% if bug.assignee %}
221 <span class="assignee">{{ bug.assignee }}</span>
222 {% endif %}
223 <a href="https://bugs.launchpad.net/bugs/{{ bug.id }}">#{{ bug.id }}</a> <span class="{{ bug.importance|importance_css_class }}">{{ bug.importance }}</span>
224 <br/>
225 <div class="project">{{ bug.project }}</div>
226 <div>{{ bug.title }}</div>
227 {% if bug.branch %}
228 <div class="merge-proposal"><a href="{{ bug|branch_url }}">{{ bug.branch|branch_name }}</a></div>
229 {% endif %}
230 </div>
231 {% endfor %}
232
233 </div>
234 {% endif %}
174 </div>235 </div>
175 {% endfor %}236 {% endfor %}
176237
@@ -195,6 +256,7 @@
195 </div>256 </div>
196 </div>257 </div>
197258
259 {% if kanban_board.include_needs_testing %}
198 <div class="position-6 width-2 cell">260 <div class="position-6 width-2 cell">
199 <div class="legend-description">261 <div class="legend-description">
200 <strong>Needs testing</strong> bugs are <em>Fix Committed</em>262 <strong>Needs testing</strong> bugs are <em>Fix Committed</em>
@@ -215,16 +277,40 @@
215 <strong>Fix released</strong> bugs are <em>Fix Released</em>.277 <strong>Fix released</strong> bugs are <em>Fix Released</em>.
216 </div>278 </div>
217 </div>279 </div>
280 {% else %}
281 <div class="position-6 width-2 cell">
282 <div class="legend-description">
283 <strong>Needs release</strong> bugs are <em>Fix
284 Committed</em> or <em>In Progress</em> with
285 an <em>Approved</em> or
286 <em>Merged</em> merge proposal.
287 </div>
288 </div>
289
290 <div class="position-8 width-2 cell">
291 <div class="legend-description">
292 <strong>Fix released</strong> bugs are <em>Fix Released</em>.
293 </div>
294 </div>
295 {% endif %}
218 </div>296 </div>
219297
220 <!-- XXX This is a hack. It'd be better to add bottom-rounded298 <!-- XXX This is a hack. It'd be better to add bottom-rounded
221 borders to the last .tile element. -->299 borders to the last .tile element. -->
222 <div id="prefooter" class="row">300 <div id="prefooter" class="row">
301 {% if kanban_board.include_needs_testing %}
223 <div class="position-0 width-12 cell">&nbsp;</div>302 <div class="position-0 width-12 cell">&nbsp;</div>
303 {% else %}
304 <div class="position-0 width-10 cell">&nbsp;</div>
305 {% endif %}
224 </div>306 </div>
225307
226 <div id="footer" class="row">308 <div id="footer" class="row">
309 {% if kanban_board.include_needs_testing %}
227 <div class="position-0 width-12 cell">Generated on {{ now }}.</div>310 <div class="position-0 width-12 cell">Generated on {{ now }}.</div>
311 {% else %}
312 <div class="position-0 width-10 cell">Generated on {{ now }}.</div>
313 {% endif %}
228 </div>314 </div>
229315
230 </div>316 </div>
231317
=== modified file 'kanban/tests/test_board.py'
--- kanban/tests/test_board.py 2011-02-17 10:07:00 +0000
+++ kanban/tests/test_board.py 2011-03-12 20:16:43 +0000
@@ -278,8 +278,8 @@
278 def test_add_queued(self):278 def test_add_queued(self):
279 """279 """
280 A L{Bug} in the 'Queued' category is stored in the280 A L{Bug} in the 'Queued' category is stored in the
281 L{BugCollectionMixin.bugs} and the L{Story.queued} list in the default281 L{BugCollectionMixin.bugs} and the L{Story.queued} lists, in the
282 story.282 default story.
283 """283 """
284 bug = Bug("1", "kanban", MEDIUM, NEW, "A title")284 bug = Bug("1", "kanban", MEDIUM, NEW, "A title")
285 kanban_board = self.create_test_class()285 kanban_board = self.create_test_class()
@@ -295,7 +295,7 @@
295 def test_add_in_progress(self):295 def test_add_in_progress(self):
296 """296 """
297 A L{Bug} in the 'In progress' category is stored in the297 A L{Bug} in the 'In progress' category is stored in the
298 L{BugCollectionMixin.bugs} and the L{Story.in_progress} list in the298 L{BugCollectionMixin.bugs} and the L{Story.in_progress} lists, in the
299 default story.299 default story.
300 """300 """
301 bug = Bug("1", "kanban", MEDIUM, IN_PROGRESS, "A title")301 bug = Bug("1", "kanban", MEDIUM, IN_PROGRESS, "A title")
@@ -312,7 +312,7 @@
312 def test_add_needs_review(self):312 def test_add_needs_review(self):
313 """313 """
314 A L{Bug} in the 'Needs review' category is stored in the314 A L{Bug} in the 'Needs review' category is stored in the
315 L{BugCollectionMixin.bugs} and the L{Story.in_progress} list in the315 L{BugCollectionMixin.bugs} and the L{Story.in_progress} lists, in the
316 default story.316 default story.
317 """317 """
318 bug = Bug("1", "kanban", MEDIUM, IN_PROGRESS, "A title",318 bug = Bug("1", "kanban", MEDIUM, IN_PROGRESS, "A title",
@@ -330,12 +330,12 @@
330 def test_add_needs_testing(self):330 def test_add_needs_testing(self):
331 """331 """
332 A L{Bug} in the 'Needs testing' category is stored in the332 A L{Bug} in the 'Needs testing' category is stored in the
333 L{BugCollectionMixin.bugs} and the L{Story.needs_testing} list in the333 L{BugCollectionMixin.bugs} and the L{Story.needs_testing} lists, in
334 default story.334 the default story.
335 """335 """
336 bug = Bug("1", "kanban", MEDIUM, IN_PROGRESS, "A title",336 bug = Bug("1", "kanban", MEDIUM, IN_PROGRESS, "A title",
337 merge_proposal="url", merge_proposal_status=APPROVED)337 merge_proposal="url", merge_proposal_status=APPROVED)
338 kanban_board = self.create_test_class()338 kanban_board = self.create_test_class(include_needs_testing=True)
339 kanban_board.add(bug)339 kanban_board.add(bug)
340 self.assertEqual([bug], kanban_board.bugs)340 self.assertEqual([bug], kanban_board.bugs)
341 self.assertEqual([], kanban_board.queued)341 self.assertEqual([], kanban_board.queued)
@@ -345,11 +345,29 @@
345 self.assertEqual([], kanban_board.needs_release)345 self.assertEqual([], kanban_board.needs_release)
346 self.assertEqual([], kanban_board.released)346 self.assertEqual([], kanban_board.released)
347347
348 def test_add_needs_testing_disabled(self):
349 """
350 A L{Bug} in the 'Needs testing' category is stored in the
351 L{BugCollectionMixin.bugs} and the L{Story.needs_release} lists, in
352 the default story, when the 'Needs testing' category is disabled.
353 """
354 bug = Bug("1", "kanban", MEDIUM, IN_PROGRESS, "A title",
355 merge_proposal="url", merge_proposal_status=APPROVED)
356 kanban_board = self.create_test_class()
357 kanban_board.add(bug)
358 self.assertEqual([bug], kanban_board.bugs)
359 self.assertEqual([], kanban_board.queued)
360 self.assertEqual([], kanban_board.in_progress)
361 self.assertEqual([], kanban_board.needs_review)
362 self.assertEqual([], kanban_board.needs_testing)
363 self.assertEqual([bug], kanban_board.needs_release)
364 self.assertEqual([], kanban_board.released)
365
348 def test_add_needs_release(self):366 def test_add_needs_release(self):
349 """367 """
350 A L{Bug} in the 'Needs release' category is stored in the368 A L{Bug} in the 'Needs release' category is stored in the
351 L{BugCollectionMixin.bugs} and the L{Story.needs_release} list in the369 L{BugCollectionMixin.bugs} and the L{Story.needs_release} lists, in
352 default story.370 the default story.
353 """371 """
354 bug = Bug("1", "kanban", MEDIUM, FIX_COMMITTED, "A title",372 bug = Bug("1", "kanban", MEDIUM, FIX_COMMITTED, "A title",
355 merge_proposal="url", merge_proposal_status=MERGED,373 merge_proposal="url", merge_proposal_status=MERGED,
@@ -367,7 +385,7 @@
367 def test_add_released(self):385 def test_add_released(self):
368 """386 """
369 A L{Bug} in the 'Released' category is stored in the387 A L{Bug} in the 'Released' category is stored in the
370 L{BugCollectionMixin.bugs} and the L{Story.released} list in the388 L{BugCollectionMixin.bugs} and the L{Story.released} lists, in the
371 default story.389 default story.
372 """390 """
373 bug = Bug("1", "kanban", MEDIUM, FIX_RELEASED, "A title")391 bug = Bug("1", "kanban", MEDIUM, FIX_RELEASED, "A title")
@@ -463,12 +481,13 @@
463class MilestoneBoardTest(BugCollectionMixinTestBase,481class MilestoneBoardTest(BugCollectionMixinTestBase,
464 StoryCollectionMixinTestBase, TestCase):482 StoryCollectionMixinTestBase, TestCase):
465483
466 def create_test_class(self):484 def create_test_class(self, include_needs_testing=None):
467 """485 """
468 Create a L{MilestoneBoard} for use in L{BugCollectionMixinTestBase}486 Create a L{MilestoneBoard} for use in L{BugCollectionMixinTestBase}
469 and L{StoryCollectionMixinTestBase} tests.487 and L{StoryCollectionMixinTestBase} tests.
470 """488 """
471 return MilestoneBoard("project", "milestone")489 return MilestoneBoard("project", "milestone",
490 include_needs_testing=include_needs_testing)
472491
473 def test_instantiate(self):492 def test_instantiate(self):
474 """493 """
@@ -484,12 +503,12 @@
484class PersonBoardTest(BugCollectionMixinTestBase, StoryCollectionMixinTestBase,503class PersonBoardTest(BugCollectionMixinTestBase, StoryCollectionMixinTestBase,
485 TestCase):504 TestCase):
486505
487 def create_test_class(self):506 def create_test_class(self, include_needs_testing=None):
488 """507 """
489 Create a L{PersonBoard} for use in L{BugCollectionMixinTestBase} and508 Create a L{PersonBoard} for use in L{BugCollectionMixinTestBase} and
490 L{StoryCollectionMixinTestBase} tests.509 L{StoryCollectionMixinTestBase} tests.
491 """510 """
492 return PersonBoard("team")511 return PersonBoard("team", include_needs_testing=include_needs_testing)
493512
494 def test_instantiate(self):513 def test_instantiate(self):
495 """514 """
@@ -503,11 +522,11 @@
503522
504class StoryTest(BugCollectionMixinTestBase, TestCase):523class StoryTest(BugCollectionMixinTestBase, TestCase):
505524
506 def create_test_class(self):525 def create_test_class(self, include_needs_testing=None):
507 """526 """
508 Create a L{Story} for use in L{BugCollectionMixinTestBase} tests.527 Create a L{Story} for use in L{BugCollectionMixinTestBase} tests.
509 """528 """
510 return Story("name")529 return Story("name", include_needs_testing=include_needs_testing)
511530
512531
513class CompareStoriesTest(TestCase):532class CompareStoriesTest(TestCase):
514533
=== added file 'media/decogrids-10.css'
--- media/decogrids-10.css 1970-01-01 00:00:00 +0000
+++ media/decogrids-10.css 2011-03-12 20:16:43 +0000
@@ -0,0 +1,74 @@
1/* The 12-column Deco Grid System.
2 * Available in multiple variants, see http://deco.gs
3 *
4 * Cells are 7.91668% (=76px)
5 * Margins are 1.04166% (=10px) (times two, left and right)
6 * Total is 10% (=96px) (which makes 10 columns)
7 *
8 * If page width is fixed to 960px width:
9 * Cell will be equivalent to 76px, left/right margin will be 10px.
10 *
11 */
12
13div.row {
14 float: left;
15 width: 100%;
16 display: block;
17 position: relative;
18}
19div.cell {
20 position: relative;
21 float: left;
22 left: 100%;
23}
24
25/* Width classes.
26 For a given cell width, the calculation is:
27 width = (total cell width) * n - (margin*2)
28 In this case: (8.333*n - 2.08333)% */
29div.width-1 { width: 7.9166% }
30div.width-2 { width: 17.916% }
31div.width-3 { width: 27.916% }
32div.width-4 { width: 37.916% }
33div.width-5 { width: 47.916% }
34div.width-6 { width: 57.916% }
35div.width-7 { width: 67.916% }
36div.width-8 { width: 77.916% }
37div.width-9 { width: 87.916% }
38div.width-10 { width: 97.916% }
39
40
41
42/* Positioning classes, these are subtracting from a rightmost
43 position, which is why they seem the wrong way around */
44/* For a given position, the calculation is:
45 -100 + (total cell width * n)
46 In this case: margin-left: -100 + (8.333*n) */
47div.position-0 { margin-left: -100% }
48div.position-1 { margin-left: -90% }
49div.position-2 { margin-left: -80% }
50div.position-3 { margin-left: -70% }
51div.position-4 { margin-left: -60% }
52div.position-5 { margin-left: -50% }
53div.position-6 { margin-left: -40% }
54div.position-7 { margin-left: -30% }
55div.position-8 { margin-left: -20% }
56div.position-9 { margin-left: -10% }
57
58/* End of the core Deco Grid System */
59
60/* Convenience classes — ¼, ½, ¾ widths and ¼, ½, ¾ positions.
61 Not strictly necessary. */
62div.width-1\3a 2 { width: 47.916%; } /* .width-1:2 */
63div.width-1\3a 4 { width: 22.916%; } /* .width-1:4 */
64div.width-3\3a 4 { width: 72.916%; } /* .width-3:4 */
65div.position-1\3a 4 { margin-left: -75.001%;} /* .position-1:4 */
66div.position-1\3a 2 { margin-left: -50.002%;} /* .position-1:2 */
67div.position-3\3a 4 { margin-left: -25.003%;} /* .position-3:4 */
68
69
70/* Special classes for ⅓, ⅔ widths and ⅓, ⅔ positions. */
71div.width-1\3a 3 { width: 31.250%; } /* .width-1:3 */
72div.width-2\3a 3 { width: 64.583%; } /* .width-2:3 */
73div.position-1\3a 3 {margin-left: -66.668%;} /* .position-1:3 */
74div.position-2\3a 3 {margin-left: -33.336%;} /* .position-2:3 */
075
=== modified file 'media/decogrids-12.css'
--- media/decogrids-12.css 2010-11-15 00:00:59 +0000
+++ media/decogrids-12.css 2011-03-12 20:16:43 +0000
@@ -1,10 +1,10 @@
1/* The 12-column Deco Grid System. 1/* The 12-column Deco Grid System.
2 * Available in multiple variants, see http://deco.gs2 * Available in multiple variants, see http://deco.gs
3 *3 *
4 * Cells are 6.25% (=60px)4 * Cells are 6.25% (=60px)
5 * Margins are 1.04166% (=10px) (times two, left and right)5 * Margins are 1.04166% (=10px) (times two, left and right)
6 * Total is 8.33333%. (=80px) (which makes 12 columns)6 * Total is 8.33333%. (=80px) (which makes 12 columns)
7 * 7 *
8 * If page width is fixed to 960px width:8 * If page width is fixed to 960px width:
9 * Cell will be equivalent to 60px, left/right margin will be 10px.9 * Cell will be equivalent to 60px, left/right margin will be 10px.
10 *10 *
@@ -22,9 +22,9 @@
22 left: 100%;22 left: 100%;
23}23}
2424
25/* Width classes. 25/* Width classes.
26 For a given cell width, the calculation is: 26 For a given cell width, the calculation is:
27 width = (total cell width) * n - (margin*2) 27 width = (total cell width) * n - (margin*2)
28 In this case: (8.333*n - 2.08333)% */28 In this case: (8.333*n - 2.08333)% */
29div.width-1 { width: 6.2500% }29div.width-1 { width: 6.2500% }
30div.width-2 { width: 14.583% }30div.width-2 { width: 14.583% }
@@ -39,7 +39,7 @@
39div.width-11 { width: 89.583% }39div.width-11 { width: 89.583% }
40div.width-12 { width: 97.916% }40div.width-12 { width: 97.916% }
4141
42/* Positioning classes, these are subtracting from a rightmost 42/* Positioning classes, these are subtracting from a rightmost
43 position, which is why they seem the wrong way around */43 position, which is why they seem the wrong way around */
44/* For a given position, the calculation is:44/* For a given position, the calculation is:
45 -100 + (total cell width * n)45 -100 + (total cell width * n)
@@ -59,7 +59,7 @@
5959
60/* End of the core Deco Grid System */60/* End of the core Deco Grid System */
6161
62/* Convenience classes — ¼, ½, ¾ widths and ¼, ½, ¾ positions. 62/* Convenience classes — ¼, ½, ¾ widths and ¼, ½, ¾ positions.
63 Not strictly necessary. */63 Not strictly necessary. */
64div.width-1\3a 2 { width: 47.916%; } /* .width-1:2 */64div.width-1\3a 2 { width: 47.916%; } /* .width-1:2 */
65div.width-1\3a 4 { width: 22.916%; } /* .width-1:4 */65div.width-1\3a 4 { width: 22.916%; } /* .width-1:4 */

Subscribers

People subscribed via source and target branches

to all changes: