blob: 0260308c2e3331df3226fb0973ba898e3a2f23c1 [file] [log] [blame]
Copybara854996b2021-09-07 19:36:02 +00001# Copyright 2016 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style
3# license that can be found in the LICENSE file or at
4# https://developers.google.com/open-source/licenses/bsd
5
6"""Unit tests for table_view_helpers classes and functions."""
7from __future__ import print_function
8from __future__ import division
9from __future__ import absolute_import
10
11import collections
12import unittest
13import logging
14
15from framework import framework_views
16from framework import table_view_helpers
17from proto import tracker_pb2
18from testing import fake
19from testing import testing_helpers
20from tracker import tracker_bizobj
21
22
23EMPTY_SEARCH_RESULTS = []
24
25SEARCH_RESULTS_WITH_LABELS = [
26 fake.MakeTestIssue(
27 789, 1, 'sum 1', 'New', 111, labels='Priority-High Mstone-1',
28 merged_into=200001, star_count=1),
29 fake.MakeTestIssue(
30 789, 2, 'sum 2', 'New', 111, labels='Priority-High Mstone-1',
31 merged_into=1, star_count=1),
32 fake.MakeTestIssue(
33 789, 3, 'sum 3', 'New', 111, labels='Priority-Low Mstone-1.1',
34 merged_into=1, star_count=1),
35 # 'Visibility-Super-High' tests that only first dash counts
36 fake.MakeTestIssue(
37 789, 4, 'sum 4', 'New', 111, labels='Visibility-Super-High',
38 star_count=1),
39 ]
40
41
42def MakeTestIssue(local_id, issue_id, summary):
43 issue = tracker_pb2.Issue()
44 issue.local_id = local_id
45 issue.issue_id = issue_id
46 issue.summary = summary
47 return issue
48
49
50class TableCellTest(unittest.TestCase):
51
52 USERS_BY_ID = {}
53
54 def setUp(self):
55 self.config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
56 self.config.field_defs = [
57 tracker_bizobj.MakeFieldDef(
58 1, 789, 'Goats', tracker_pb2.FieldTypes.INT_TYPE, None, None,
59 False, False, False, None, None, None, False, None, None, None,
60 None, 'Num of Goats in the season', False, is_phase_field=True),
61 tracker_bizobj.MakeFieldDef(
62 2, 789, 'DogNames', tracker_pb2.FieldTypes.STR_TYPE, None, None,
63 False, False, False, None, None, None, False, None, None, None,
64 None, 'good dog names', False),
65 tracker_bizobj.MakeFieldDef(
66 3, 789, 'Approval', tracker_pb2.FieldTypes.APPROVAL_TYPE,
67 None, None, False, False, False, None, None, None, False, None,
68 None, None, None, 'Tracks review from cows', False)
69 ]
70 self.config.approval_defs = [tracker_pb2.ApprovalDef(approval_id=3)]
71 self.issue = MakeTestIssue(
72 local_id=1, issue_id=100001, summary='One')
73 self.issue.field_values = [
74 tracker_bizobj.MakeFieldValue(
75 1, 34, None, None, None, None, False, phase_id=23),
76 tracker_bizobj.MakeFieldValue(
77 1, 35, None, None, None, None, False, phase_id=24),
78 tracker_bizobj.MakeFieldValue(
79 2, None, 'Waffles', None, None, None, False),
80 ]
81 self.issue.phases = [
82 tracker_pb2.Phase(phase_id=23, name='winter'),
83 tracker_pb2.Phase(phase_id=24, name='summer')]
84 self.issue.approval_values = [
85 tracker_pb2.ApprovalValue(
86 approval_id=3, approver_ids=[111, 222, 333])]
87 self.users_by_id = {
88 111: framework_views.StuffUserView(111, 'foo@example.com', False),
89 222: framework_views.StuffUserView(222, 'foo2@example.com', True),
90 }
91
92 self.summary_table_cell_kws = {
93 'col': None,
94 'users_by_id': {},
95 'non_col_labels': [('lab', False)],
96 'label_values': {},
97 'related_issues': {},
98 'config': 'fake_config',
99 }
100
101 def testTableCellSummary(self):
102 """TableCellSummary stores the data given to it."""
103 cell = table_view_helpers.TableCellSummary(
104 MakeTestIssue(4, 4, 'Lame default summary.'),
105 **self.summary_table_cell_kws)
106 self.assertEqual(cell.type, table_view_helpers.CELL_TYPE_SUMMARY)
107 self.assertEqual(cell.values[0].item, 'Lame default summary.')
108 self.assertEqual(cell.non_column_labels[0].value, 'lab')
109
110 def testTableCellSummary_NoPythonEscaping(self):
111 """TableCellSummary stores the summary without escaping it in python."""
112 cell = table_view_helpers.TableCellSummary(
113 MakeTestIssue(4, 4, '<b>bold</b> "summary".'),
114 **self.summary_table_cell_kws)
115 self.assertEqual(cell.values[0].item,'<b>bold</b> "summary".')
116
117 def testTableCellCustom_normal(self):
118 """TableCellCustom stores the value of a custom FieldValue."""
119 cell_dognames = table_view_helpers.TableCellCustom(
120 self.issue, col='dognames', config=self.config)
121 self.assertEqual(cell_dognames.type, table_view_helpers.CELL_TYPE_ATTR)
122 self.assertEqual(cell_dognames.values[0].item, 'Waffles')
123
124 def testTableCellCustom_phasefields(self):
125 """TableCellCustom stores the value of a custom FieldValue."""
126 cell_winter = table_view_helpers.TableCellCustom(
127 self.issue, col='winter.goats', config=self.config)
128 self.assertEqual(cell_winter.type, table_view_helpers.CELL_TYPE_ATTR)
129 self.assertEqual(cell_winter.values[0].item, 34)
130
131 cell_summer = table_view_helpers.TableCellCustom(
132 self.issue, col='summer.goats', config=self.config)
133 self.assertEqual(cell_summer.type, table_view_helpers.CELL_TYPE_ATTR)
134 self.assertEqual(cell_summer.values[0].item, 35)
135
136 def testTableCellApprovalStatus(self):
137 """TableCellApprovalStatus stores the status of an ApprovalValue."""
138 cell = table_view_helpers.TableCellApprovalStatus(
139 self.issue, col='Approval', config=self.config)
140 self.assertEqual(cell.type, table_view_helpers.CELL_TYPE_ATTR)
141 self.assertEqual(cell.values[0].item, 'NOT_SET')
142
143 def testTableCellApprovalApprover(self):
144 """TableCellApprovalApprover stores the approvers of an ApprovalValue."""
145 cell = table_view_helpers.TableCellApprovalApprover(
146 self.issue, col='Approval-approver', config=self.config,
147 users_by_id=self.users_by_id)
148 self.assertEqual(cell.type, table_view_helpers.CELL_TYPE_ATTR)
149 self.assertEqual(len(cell.values), 2)
150 self.assertItemsEqual([cell.values[0].item, cell.values[1].item],
151 ['foo@example.com', 'f...@example.com'])
152
153 # TODO(jrobbins): TableCellProject, TableCellStars
154
155
156
157class TableViewHelpersTest(unittest.TestCase):
158
159 def setUp(self):
160 self.default_cols = 'a b c'
161 self.builtin_cols = ['a', 'b', 'x', 'y', 'z']
162 self.config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
163
164 def testComputeUnshownColumns_CommonCase(self):
165 shown_cols = ['a', 'b', 'c']
166 config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
167 config.default_col_spec = self.default_cols
168 config.well_known_labels = []
169
170 unshown = table_view_helpers.ComputeUnshownColumns(
171 EMPTY_SEARCH_RESULTS, shown_cols, config, self.builtin_cols)
172 self.assertEqual(unshown, ['x', 'y', 'z'])
173
174 unshown = table_view_helpers.ComputeUnshownColumns(
175 SEARCH_RESULTS_WITH_LABELS, shown_cols, config, self.builtin_cols)
176 self.assertEqual(
177 unshown, ['Mstone', 'Priority', 'Visibility', 'x', 'y', 'z'])
178
179 def testComputeUnshownColumns_MoreBuiltins(self):
180 shown_cols = ['a', 'b', 'c', 'x', 'y']
181 config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
182 config.default_col_spec = self.default_cols
183 config.well_known_labels = []
184
185 unshown = table_view_helpers.ComputeUnshownColumns(
186 EMPTY_SEARCH_RESULTS, shown_cols, config, self.builtin_cols)
187 self.assertEqual(unshown, ['z'])
188
189 unshown = table_view_helpers.ComputeUnshownColumns(
190 SEARCH_RESULTS_WITH_LABELS, shown_cols, config, self.builtin_cols)
191 self.assertEqual(unshown, ['Mstone', 'Priority', 'Visibility', 'z'])
192
193 def testComputeUnshownColumns_NotAllDefaults(self):
194 shown_cols = ['a', 'b']
195 config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
196 config.default_col_spec = self.default_cols
197 config.well_known_labels = []
198
199 unshown = table_view_helpers.ComputeUnshownColumns(
200 EMPTY_SEARCH_RESULTS, shown_cols, config, self.builtin_cols)
201 self.assertEqual(unshown, ['c', 'x', 'y', 'z'])
202
203 unshown = table_view_helpers.ComputeUnshownColumns(
204 SEARCH_RESULTS_WITH_LABELS, shown_cols, config, self.builtin_cols)
205 self.assertEqual(
206 unshown, ['Mstone', 'Priority', 'Visibility', 'c', 'x', 'y', 'z'])
207
208 def testComputeUnshownColumns_ExtraNonDefaults(self):
209 shown_cols = ['a', 'b', 'c', 'd', 'e', 'f']
210 config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
211 config.default_col_spec = self.default_cols
212 config.well_known_labels = []
213
214 unshown = table_view_helpers.ComputeUnshownColumns(
215 EMPTY_SEARCH_RESULTS, shown_cols, config, self.builtin_cols)
216 self.assertEqual(unshown, ['x', 'y', 'z'])
217
218 unshown = table_view_helpers.ComputeUnshownColumns(
219 SEARCH_RESULTS_WITH_LABELS, shown_cols, config, self.builtin_cols)
220 self.assertEqual(
221 unshown, ['Mstone', 'Priority', 'Visibility', 'x', 'y', 'z'])
222
223 def testComputeUnshownColumns_UserColumnsShown(self):
224 shown_cols = ['a', 'b', 'c', 'Priority']
225 config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
226 config.default_col_spec = self.default_cols
227 config.well_known_labels = []
228
229 unshown = table_view_helpers.ComputeUnshownColumns(
230 EMPTY_SEARCH_RESULTS, shown_cols, config, self.builtin_cols)
231 self.assertEqual(unshown, ['x', 'y', 'z'])
232
233 unshown = table_view_helpers.ComputeUnshownColumns(
234 SEARCH_RESULTS_WITH_LABELS, shown_cols, config, self.builtin_cols)
235 self.assertEqual(unshown, ['Mstone', 'Visibility', 'x', 'y', 'z'])
236
237 def testComputeUnshownColumns_EverythingShown(self):
238 shown_cols = [
239 'a', 'b', 'c', 'x', 'y', 'z', 'Priority', 'Mstone', 'Visibility']
240 config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
241 config.default_col_spec = self.default_cols
242 config.well_known_labels = []
243
244 unshown = table_view_helpers.ComputeUnshownColumns(
245 EMPTY_SEARCH_RESULTS, shown_cols, config, self.builtin_cols)
246 self.assertEqual(unshown, [])
247
248 unshown = table_view_helpers.ComputeUnshownColumns(
249 SEARCH_RESULTS_WITH_LABELS, shown_cols, config, self.builtin_cols)
250 self.assertEqual(unshown, [])
251
252 def testComputeUnshownColumns_NothingShown(self):
253 shown_cols = []
254 config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
255 config.default_col_spec = self.default_cols
256 config.well_known_labels = []
257
258 unshown = table_view_helpers.ComputeUnshownColumns(
259 EMPTY_SEARCH_RESULTS, shown_cols, config, self.builtin_cols)
260 self.assertEqual(unshown, ['a', 'b', 'c', 'x', 'y', 'z'])
261
262 unshown = table_view_helpers.ComputeUnshownColumns(
263 SEARCH_RESULTS_WITH_LABELS, shown_cols, config, self.builtin_cols)
264 self.assertEqual(
265 unshown,
266 ['Mstone', 'Priority', 'Visibility', 'a', 'b', 'c', 'x', 'y', 'z'])
267
268 def testComputeUnshownColumns_NoBuiltins(self):
269 shown_cols = ['a', 'b', 'c']
270 config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
271 config.default_col_spec = ''
272 config.well_known_labels = []
273 builtin_cols = []
274
275 unshown = table_view_helpers.ComputeUnshownColumns(
276 EMPTY_SEARCH_RESULTS, shown_cols, config, builtin_cols)
277 self.assertEqual(unshown, [])
278
279 unshown = table_view_helpers.ComputeUnshownColumns(
280 SEARCH_RESULTS_WITH_LABELS, shown_cols, config, builtin_cols)
281 self.assertEqual(unshown, ['Mstone', 'Priority', 'Visibility'])
282
283 def testComputeUnshownColumns_FieldDefs(self):
284 search_results = [
285 fake.MakeTestIssue(
286 789, 1, 'sum 1', 'New', 111,
287 field_values=[
288 tracker_bizobj.MakeFieldValue(
289 5, 74, None, None, None, None, False, phase_id=4),
290 tracker_bizobj.MakeFieldValue(
291 6, 78, None, None, None, None, False, phase_id=5)],
292 phases=[
293 tracker_pb2.Phase(phase_id=4, name='goats'),
294 tracker_pb2.Phase(phase_id=5, name='sheep')]),
295 fake.MakeTestIssue(
296 789, 2, 'sum 2', 'New', 111,
297 field_values=[
298 tracker_bizobj.MakeFieldValue(
299 5, 74, None, None, None, None, False, phase_id=3),
300 tracker_bizobj.MakeFieldValue(
301 6, 77, None, None, None, None, False, phase_id=3)],
302 phases=[
303 tracker_pb2.Phase(phase_id=3, name='Goats'),
304 tracker_pb2.Phase(phase_id=3, name='Goats-Exp')]),
305 ]
306
307 shown_cols = ['a', 'b', 'a1', 'a2-approver', 'f3', 'goats.g1', 'sheep.g2']
308 config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
309 config.default_col_spec = ''
310 config.well_known_labels = []
311 config.field_defs = [
312 tracker_bizobj.MakeFieldDef(
313 1, 789, 'a1', tracker_pb2.FieldTypes.APPROVAL_TYPE,
314 None, None, False, False, False, None, None, None, False, None,
315 None, None, None, 'Tracks review from cows', False),
316 tracker_bizobj.MakeFieldDef(
317 2, 789, 'a2', tracker_pb2.FieldTypes.APPROVAL_TYPE,
318 None, None, False, False, False, None, None, None, False, None,
319 None, None, None, 'Tracks review from chickens', False),
320 tracker_bizobj.MakeFieldDef(
321 3, 789, 'f3', tracker_pb2.FieldTypes.STR_TYPE,
322 None, None, False, False, False, None, None, None, False, None,
323 None, None, None, 'cow names', False),
324 tracker_bizobj.MakeFieldDef(
325 4, 789, 'f4', tracker_pb2.FieldTypes.INT_TYPE,
326 None, None, False, False, False, None, None, None, False, None,
327 None, None, None, 'chicken gobbles', False),
328 tracker_bizobj.MakeFieldDef(
329 5, 789, 'g1', tracker_pb2.FieldTypes.INT_TYPE,
330 None, None, False, False, False, None, None, None, False, None,
331 None, None, None, 'fluff', False, is_phase_field=True),
332 tracker_bizobj.MakeFieldDef(
333 6, 789, 'g2', tracker_pb2.FieldTypes.INT_TYPE,
334 None, None, False, False, False, None, None, None, False, None,
335 None, None, None, 'poof', False, is_phase_field=True),
336 ]
337 builtin_cols = []
338
339 unshown = table_view_helpers.ComputeUnshownColumns(
340 search_results, shown_cols, config, builtin_cols)
341 self.assertEqual(unshown, [
342 'a1-approver', 'a2', 'f4',
343 'goats-exp.g1', 'goats-exp.g2', 'goats.g2', 'sheep.g1'])
344
345 def testExtractUniqueValues_NoColumns(self):
346 column_values = table_view_helpers.ExtractUniqueValues(
347 [], SEARCH_RESULTS_WITH_LABELS, {}, self.config, {})
348 self.assertEqual([], column_values)
349
350 def testExtractUniqueValues_NoResults(self):
351 cols = ['type', 'priority', 'owner', 'status', 'stars', 'attachments']
352 column_values = table_view_helpers.ExtractUniqueValues(
353 cols, EMPTY_SEARCH_RESULTS, {}, self.config, {})
354 self.assertEqual(6, len(column_values))
355 for index, col in enumerate(cols):
356 self.assertEqual(index, column_values[index].col_index)
357 self.assertEqual(col, column_values[index].column_name)
358 self.assertEqual([], column_values[index].filter_values)
359
360 def testExtractUniqueValues_ExplicitResults(self):
361 cols = ['priority', 'owner', 'status', 'stars', 'mstone', 'foo']
362 users_by_id = {
363 111: framework_views.StuffUserView(111, 'foo@example.com', True),
364 }
365 column_values = table_view_helpers.ExtractUniqueValues(
366 cols, SEARCH_RESULTS_WITH_LABELS, users_by_id, self.config, {})
367 self.assertEqual(len(cols), len(column_values))
368
369 self.assertEqual('priority', column_values[0].column_name)
370 self.assertEqual(['High', 'Low'], column_values[0].filter_values)
371
372 self.assertEqual('owner', column_values[1].column_name)
373 self.assertEqual(['f...@example.com'], column_values[1].filter_values)
374
375 self.assertEqual('status', column_values[2].column_name)
376 self.assertEqual(['New'], column_values[2].filter_values)
377
378 self.assertEqual('stars', column_values[3].column_name)
379 self.assertEqual([1], column_values[3].filter_values)
380
381 self.assertEqual('mstone', column_values[4].column_name)
382 self.assertEqual(['1', '1.1'], column_values[4].filter_values)
383
384 self.assertEqual('foo', column_values[5].column_name)
385 self.assertEqual([], column_values[5].filter_values)
386
387 # self.assertEquals('mergedinto', column_values[6].column_name)
388 # self.assertEquals(
389 # ['1', 'other-project:1'], column_values[6].filter_values)
390
391 def testExtractUniqueValues_CombinedColumns(self):
392 cols = ['priority/pri', 'owner', 'status', 'stars', 'mstone/milestone']
393 users_by_id = {
394 111: framework_views.StuffUserView(111, 'foo@example.com', True),
395 }
396 issue = fake.MakeTestIssue(
397 789, 5, 'sum 5', 'New', 111, merged_into=200001,
398 labels='Priority-High Pri-0 Milestone-1.0 mstone-1',
399 star_count=15)
400
401 column_values = table_view_helpers.ExtractUniqueValues(
402 cols, SEARCH_RESULTS_WITH_LABELS + [issue], users_by_id,
403 self.config, {})
404 self.assertEqual(5, len(column_values))
405
406 self.assertEqual('priority/pri', column_values[0].column_name)
407 self.assertEqual(['0', 'High', 'Low'], column_values[0].filter_values)
408
409 self.assertEqual('owner', column_values[1].column_name)
410 self.assertEqual(['f...@example.com'], column_values[1].filter_values)
411
412 self.assertEqual('status', column_values[2].column_name)
413 self.assertEqual(['New'], column_values[2].filter_values)
414
415 self.assertEqual('stars', column_values[3].column_name)
416 self.assertEqual([1, 15], column_values[3].filter_values)
417
418 self.assertEqual('mstone/milestone', column_values[4].column_name)
419 self.assertEqual(['1', '1.0', '1.1'], column_values[4].filter_values)
420
421 def testExtractUniqueValues_DerivedValues(self):
422 cols = ['priority', 'milestone', 'owner', 'status']
423 users_by_id = {
424 111: framework_views.StuffUserView(111, 'foo@example.com', True),
425 222: framework_views.StuffUserView(222, 'bar@example.com', True),
426 333: framework_views.StuffUserView(333, 'lol@example.com', True),
427 }
428 search_results = [
429 fake.MakeTestIssue(
430 789, 1, 'sum 1', '', 111, labels='Priority-High Milestone-1.0',
431 derived_labels='Milestone-2.0 Foo', derived_status='Started'),
432 fake.MakeTestIssue(
433 789, 2, 'sum 2', 'New', 111, labels='Priority-High Milestone-1.0',
434 derived_owner_id=333), # Not seen because of owner_id
435 fake.MakeTestIssue(
436 789, 3, 'sum 3', 'New', 0, labels='Priority-Low Milestone-1.1',
437 derived_owner_id=222),
438 ]
439
440 column_values = table_view_helpers.ExtractUniqueValues(
441 cols, search_results, users_by_id, self.config, {})
442 self.assertEqual(4, len(column_values))
443
444 self.assertEqual('priority', column_values[0].column_name)
445 self.assertEqual(['High', 'Low'], column_values[0].filter_values)
446
447 self.assertEqual('milestone', column_values[1].column_name)
448 self.assertEqual(['1.0', '1.1', '2.0'], column_values[1].filter_values)
449
450 self.assertEqual('owner', column_values[2].column_name)
451 self.assertEqual(
452 ['b...@example.com', 'f...@example.com'],
453 column_values[2].filter_values)
454
455 self.assertEqual('status', column_values[3].column_name)
456 self.assertEqual(['New', 'Started'], column_values[3].filter_values)
457
458 def testExtractUniqueValues_ColumnsRobustness(self):
459 cols = ['reporter', 'cc', 'owner', 'status', 'attachments']
460 search_results = [
461 tracker_pb2.Issue(),
462 ]
463 column_values = table_view_helpers.ExtractUniqueValues(
464 cols, search_results, {}, self.config, {})
465
466 self.assertEqual(5, len(column_values))
467 for col_val in column_values:
468 if col_val.column_name == 'attachments':
469 self.assertEqual([0], col_val.filter_values)
470 else:
471 self.assertEqual([], col_val.filter_values)
472
473 def testMakeTableData_Empty(self):
474 visible_results = []
475 lower_columns = []
476 cell_factories = {}
477 table_data = table_view_helpers.MakeTableData(
478 visible_results, [], lower_columns, lower_columns,
479 cell_factories, [], 'unused function', {}, set(), self.config)
480 self.assertEqual([], table_data)
481
482 lower_columns = ['type', 'priority', 'summary', 'stars']
483 cell_factories = {
484 'summary': table_view_helpers.TableCellSummary,
485 'stars': table_view_helpers.TableCellStars,
486 }
487
488 table_data = table_view_helpers.MakeTableData(
489 visible_results, [], lower_columns, [], {},
490 cell_factories, 'unused function', {}, set(), self.config)
491 self.assertEqual([], table_data)
492
493 def testMakeTableData_Normal(self):
494 art = fake.MakeTestIssue(
495 789, 1, 'sum 1', 'New', 111, labels='Type-Defect Priority-Medium')
496 visible_results = [art]
497 lower_columns = ['type', 'priority', 'summary', 'stars']
498 cell_factories = {
499 'summary': table_view_helpers.TableCellSummary,
500 'stars': table_view_helpers.TableCellStars,
501 }
502
503 table_data = table_view_helpers.MakeTableData(
504 visible_results, [], lower_columns, lower_columns, {},
505 cell_factories, lambda art: 'id', {}, set(), self.config)
506 self.assertEqual(1, len(table_data))
507 row = table_data[0]
508 self.assertEqual(4, len(row.cells))
509 self.assertEqual('Defect', row.cells[0].values[0].item)
510
511 def testMakeTableData_Groups(self):
512 art = fake.MakeTestIssue(
513 789, 1, 'sum 1', 'New', 111, labels='Type-Defect Priority-Medium')
514 visible_results = [art]
515 lower_columns = ['type', 'priority', 'summary', 'stars']
516 lower_group_by = ['priority']
517 cell_factories = {
518 'summary': table_view_helpers.TableCellSummary,
519 'stars': table_view_helpers.TableCellStars,
520 }
521
522 table_data = table_view_helpers.MakeTableData(
523 visible_results, [], lower_columns, lower_group_by, {},
524 cell_factories, lambda art: 'id', {}, set(), self.config)
525 self.assertEqual(1, len(table_data))
526 row = table_data[0]
527 self.assertEqual(1, len(row.group.cells))
528 self.assertEqual('Medium', row.group.cells[0].values[0].item)
529
530 def testMakeRowData(self):
531 art = fake.MakeTestIssue(
532 789, 1, 'sum 1', 'New', 111, labels='Type-Defect Priority-Medium',
533 star_count=1)
534 columns = ['type', 'priority', 'summary', 'stars']
535
536 cell_factories = [table_view_helpers.TableCellKeyLabels,
537 table_view_helpers.TableCellKeyLabels,
538 table_view_helpers.TableCellSummary,
539 table_view_helpers.TableCellStars]
540
541 # a result is an table_view_helpers.TableRow object with a "cells" field
542 # containing a list of table_view_helpers.TableCell objects.
543 result = table_view_helpers.MakeRowData(
544 art, columns, {}, cell_factories, {}, set(), self.config, {})
545
546 self.assertEqual(len(columns), len(result.cells))
547
548 for i in range(len(columns)):
549 cell = result.cells[i]
550 self.assertEqual(i, cell.col_index)
551
552 self.assertEqual(table_view_helpers.CELL_TYPE_ATTR, result.cells[0].type)
553 self.assertEqual('Defect', result.cells[0].values[0].item)
554 self.assertFalse(result.cells[0].values[0].is_derived)
555
556 self.assertEqual(table_view_helpers.CELL_TYPE_ATTR, result.cells[1].type)
557 self.assertEqual('Medium', result.cells[1].values[0].item)
558 self.assertFalse(result.cells[1].values[0].is_derived)
559
560 self.assertEqual(
561 table_view_helpers.CELL_TYPE_SUMMARY, result.cells[2].type)
562 self.assertEqual('sum 1', result.cells[2].values[0].item)
563 self.assertFalse(result.cells[2].values[0].is_derived)
564
565 self.assertEqual(table_view_helpers.CELL_TYPE_ATTR, result.cells[3].type)
566 self.assertEqual(1, result.cells[3].values[0].item)
567 self.assertFalse(result.cells[3].values[0].is_derived)
568
569 def testAccumulateLabelValues_Empty(self):
570 label_values, non_col_labels = collections.defaultdict(list), []
571 table_view_helpers._AccumulateLabelValues(
572 [], [], label_values, non_col_labels)
573 self.assertEqual({}, label_values)
574 self.assertEqual([], non_col_labels)
575
576 label_values, non_col_labels = collections.defaultdict(list), []
577 table_view_helpers._AccumulateLabelValues(
578 [], ['Type', 'Priority'], label_values, non_col_labels)
579 self.assertEqual({}, label_values)
580 self.assertEqual([], non_col_labels)
581
582 def testAccumulateLabelValues_OneWordLabels(self):
583 label_values, non_col_labels = collections.defaultdict(list), []
584 table_view_helpers._AccumulateLabelValues(
585 ['HelloThere'], [], label_values, non_col_labels)
586 self.assertEqual({}, label_values)
587 self.assertEqual([('HelloThere', False)], non_col_labels)
588
589 label_values, non_col_labels = collections.defaultdict(list), []
590 table_view_helpers._AccumulateLabelValues(
591 ['HelloThere'], [], label_values, non_col_labels, is_derived=True)
592 self.assertEqual({}, label_values)
593 self.assertEqual([('HelloThere', True)], non_col_labels)
594
595 def testAccumulateLabelValues_KeyValueLabels(self):
596 label_values, non_col_labels = collections.defaultdict(list), []
597 table_view_helpers._AccumulateLabelValues(
598 ['Type-Defect', 'Milestone-Soon'], ['type', 'milestone'],
599 label_values, non_col_labels)
600 self.assertEqual(
601 {'type': [('Defect', False)],
602 'milestone': [('Soon', False)]},
603 label_values)
604 self.assertEqual([], non_col_labels)
605
606 def testAccumulateLabelValues_MultiValueLabels(self):
607 label_values, non_col_labels = collections.defaultdict(list), []
608 table_view_helpers._AccumulateLabelValues(
609 ['OS-Mac', 'OS-Linux'], ['os', 'arch'],
610 label_values, non_col_labels)
611 self.assertEqual(
612 {'os': [('Mac', False), ('Linux', False)]},
613 label_values)
614 self.assertEqual([], non_col_labels)
615
616 def testAccumulateLabelValues_MultiPartLabels(self):
617 label_values, non_col_labels = collections.defaultdict(list), []
618 table_view_helpers._AccumulateLabelValues(
619 ['OS-Mac-Server', 'OS-Mac-Laptop'], ['os', 'os-mac'],
620 label_values, non_col_labels)
621 self.assertEqual(
622 {'os': [('Mac-Server', False), ('Mac-Laptop', False)],
623 'os-mac': [('Server', False), ('Laptop', False)],
624 },
625 label_values)
626 self.assertEqual([], non_col_labels)
627
628 def testChooseCellFactory(self):
629 """We choose the right kind of table cell for the specified column."""
630 cell_factories = {
631 'summary': table_view_helpers.TableCellSummary,
632 'stars': table_view_helpers.TableCellStars,
633 }
634 os_fd = tracker_bizobj.MakeFieldDef(
635 1, 789, 'os', tracker_pb2.FieldTypes.ENUM_TYPE, None, None, False,
636 False, False, None, None, None, False, None, None, None, None,
637 'Operating system', False)
638 deadline_fd = tracker_bizobj.MakeFieldDef(
639 2, 789, 'deadline', tracker_pb2.FieldTypes.DATE_TYPE, None, None, False,
640 False, False, None, None, None, False, None, None, None, None,
641 'Deadline to resolve issue', False)
642 approval_fd = tracker_bizobj.MakeFieldDef(
643 3, 789, 'CowApproval', tracker_pb2.FieldTypes.APPROVAL_TYPE,
644 None, None, False,
645 False, False, None, None, None, False, None, None, None, None,
646 'Tracks reviews from cows', False)
647 goats_fd = tracker_bizobj.MakeFieldDef(
648 4, 789, 'goats', tracker_pb2.FieldTypes.INT_TYPE, None, None, False,
649 False, False, None, None, None, False, None, None, None, None,
650 'Num goats in each phase', False, is_phase_field=True)
651 self.config.field_defs = [os_fd, deadline_fd, approval_fd, goats_fd]
652
653 # The column is defined in cell_factories.
654 actual = table_view_helpers.ChooseCellFactory(
655 'summary', cell_factories, self.config)
656 self.assertEqual(table_view_helpers.TableCellSummary, actual)
657
658 # The column is a composite column.
659 actual = table_view_helpers.ChooseCellFactory(
660 'summary/stars', cell_factories, self.config)
661 self.assertEqual('FactoryClass', actual.__name__)
662
663 # The column is a enum custom field, so it is treated like a label.
664 actual = table_view_helpers.ChooseCellFactory(
665 'os', cell_factories, self.config)
666 self.assertEqual(table_view_helpers.TableCellKeyLabels, actual)
667
668 # The column is a non-enum custom field.
669 actual = table_view_helpers.ChooseCellFactory(
670 'deadline', cell_factories, self.config)
671 self.assertEqual(
672 [(table_view_helpers.TableCellCustom, 'deadline'),
673 (table_view_helpers.TableCellKeyLabels, 'deadline')],
674 actual.factory_col_list)
675
676 # The column is an approval custom field.
677 actual = table_view_helpers.ChooseCellFactory(
678 'CowApproval', cell_factories, self.config)
679 self.assertEqual(
680 [(table_view_helpers.TableCellApprovalStatus, 'CowApproval'),
681 (table_view_helpers.TableCellKeyLabels, 'CowApproval')],
682 actual.factory_col_list)
683
684 # The column is an approval custom field with '-approver'.
685 actual = table_view_helpers.ChooseCellFactory(
686 'CowApproval-approver', cell_factories, self.config)
687 self.assertEqual(
688 [(table_view_helpers.TableCellApprovalApprover, 'CowApproval-approver'),
689 (table_view_helpers.TableCellKeyLabels, 'CowApproval-approver')],
690 actual.factory_col_list)
691
692 # The column specifies a phase custom field.
693 actual = table_view_helpers.ChooseCellFactory(
694 'winter.goats', cell_factories, self.config)
695 self.assertEqual(
696 [(table_view_helpers.TableCellCustom, 'winter.goats'),
697 (table_view_helpers.TableCellKeyLabels, 'winter.goats')],
698 actual.factory_col_list)
699
700
701 # Column that don't match one of the other cases is assumed to be a label.
702 actual = table_view_helpers.ChooseCellFactory(
703 'reward', cell_factories, self.config)
704 self.assertEqual(table_view_helpers.TableCellKeyLabels, actual)
705
706 def testCompositeFactoryTableCell_Empty(self):
707 """If we made a composite of zero columns, it would have no values."""
708 composite = table_view_helpers.CompositeFactoryTableCell([])
709 cell = composite('artifact')
710 self.assertEqual([], cell.values)
711
712 def testCompositeFactoryTableCell_Normal(self):
713 """If we make a composite, it has values from each of the sub cells."""
714 composite = table_view_helpers.CompositeFactoryTableCell(
715 [(sub_factory_1, 'col1'),
716 (sub_factory_2, 'col2')])
717
718 cell = composite('artifact')
719 self.assertEqual(
720 ['sub_cell_1_col1',
721 'sub_cell_2_col2'],
722 cell.values)
723
724 def testCompositeColTableCell_Empty(self):
725 """If we made a composite of zero columns, it would have no values."""
726 composite = table_view_helpers.CompositeColTableCell([], {}, self.config)
727 cell = composite('artifact')
728 self.assertEqual([], cell.values)
729
730
731 def testCompositeColTableCell_Normal(self):
732 """If we make a composite, it has values from each of the sub cells."""
733 composite = table_view_helpers.CompositeColTableCell(
734 ['col1', 'col2'],
735 {'col1': sub_factory_1, 'col2': sub_factory_2},
736 self.config)
737 cell = composite('artifact')
738 self.assertEqual(
739 ['sub_cell_1_col1',
740 'sub_cell_2_col2'],
741 cell.values)
742
743
744def sub_factory_1(_art, **kw):
745 return testing_helpers.Blank(
746 values=['sub_cell_1_%s' % kw['col']],
747 non_column_labels=[])
748
749
750def sub_factory_2(_art, **kw):
751 return testing_helpers.Blank(
752 values=['sub_cell_2_%s' % kw['col']],
753 non_column_labels=[])