3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
16 from six import StringIO
20 from cliff.formatters import table
21 from cliff.tests import test_columns
25 def __init__(self, max_width=0, print_empty=False):
27 self.max_width = max_width
29 # Envvar is only taken into account iff CLI parameter not given
30 self.max_width = int(os.environ.get('CLIFF_MAX_TERM_WIDTH', 0))
31 self.print_empty = print_empty
34 def _table_tester_helper(tags, data, extra_args=None):
35 """Get table output as a string, formatted according to
36 CLI arguments, environment variables and terminal size
38 tags - tuple of strings for data tags (column headers or fields)
39 data - tuple of strings for single data row
40 - list of tuples of strings for multiple rows of data
41 extra_args - an instance of class args
42 - a list of strings for CLI arguments
44 sf = table.TableFormatter()
46 if extra_args is None:
47 # Default to no CLI arguments
49 elif type(extra_args) == args:
50 # Use the given CLI arguments
51 parsed_args = extra_args
53 # Parse arguments as if passed on the command-line
54 parser = argparse.ArgumentParser(description='Testing...')
55 sf.add_argument_group(parser)
56 parsed_args = parser.parse_args(extra_args)
59 emitter = sf.emit_list if type(data) is list else sf.emit_one
60 emitter(tags, data, output, parsed_args)
61 return output.getvalue()
64 @mock.patch('cliff.utils.terminal_width')
65 def test_table_formatter(tw):
67 c = ('a', 'b', 'c', 'd')
68 d = ('A', 'B', 'C', 'test\rcarriage\r\nreturn')
70 +-------+---------------+
72 +-------+---------------+
78 +-------+---------------+
80 assert expected == _table_tester_helper(c, d)
83 # Multi-line output when width is restricted to 42 columns
84 expected_ml_val = '''\
85 +-------+--------------------------------+
87 +-------+--------------------------------+
91 | d | dddddddddddddddddddddddddddddd |
92 | | dddddddddddddddddddddddddddddd |
93 | | ddddddddddddddddd |
94 +-------+--------------------------------+
97 # Multi-line output when width is restricted to 80 columns
98 expected_ml_80_val = '''\
99 +-------+----------------------------------------------------------------------+
101 +-------+----------------------------------------------------------------------+
105 | d | dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd |
107 +-------+----------------------------------------------------------------------+
110 # Single-line output, for when no line length restriction apply
111 expected_sl_val = '''\
112 +-------+-------------------------------------------------------------------------------+
114 +-------+-------------------------------------------------------------------------------+
118 | d | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd |
119 +-------+-------------------------------------------------------------------------------+
123 @mock.patch('cliff.utils.terminal_width')
124 def test_table_formatter_no_cli_param(tw):
126 c = ('a', 'b', 'c', 'd')
127 d = ('A', 'B', 'C', 'd' * 77)
128 assert expected_ml_80_val == _table_tester_helper(c, d, extra_args=args())
131 @mock.patch('cliff.utils.terminal_width')
132 def test_table_formatter_cli_param(tw):
134 c = ('a', 'b', 'c', 'd')
135 d = ('A', 'B', 'C', 'd' * 77)
136 assert (expected_ml_val ==
137 _table_tester_helper(c, d, extra_args=['--max-width', '42']))
140 @mock.patch('cliff.utils.terminal_width')
141 def test_table_formatter_no_cli_param_unlimited_tw(tw):
143 c = ('a', 'b', 'c', 'd')
144 d = ('A', 'B', 'C', 'd' * 77)
145 # output should not be wrapped to multiple lines
146 assert expected_sl_val == _table_tester_helper(c, d, extra_args=args())
149 @mock.patch('cliff.utils.terminal_width')
150 def test_table_formatter_cli_param_unlimited_tw(tw):
152 c = ('a', 'b', 'c', 'd')
153 d = ('A', 'B', 'C', 'd' * 77)
154 assert (expected_ml_val ==
155 _table_tester_helper(c, d, extra_args=['--max-width', '42']))
158 @mock.patch('cliff.utils.terminal_width')
159 @mock.patch.dict(os.environ, {'CLIFF_MAX_TERM_WIDTH': '666'})
160 def test_table_formatter_cli_param_envvar_big(tw):
162 c = ('a', 'b', 'c', 'd')
163 d = ('A', 'B', 'C', 'd' * 77)
164 assert (expected_ml_val ==
165 _table_tester_helper(c, d, extra_args=['--max-width', '42']))
168 @mock.patch('cliff.utils.terminal_width')
169 @mock.patch.dict(os.environ, {'CLIFF_MAX_TERM_WIDTH': '23'})
170 def test_table_formatter_cli_param_envvar_tiny(tw):
172 c = ('a', 'b', 'c', 'd')
173 d = ('A', 'B', 'C', 'd' * 77)
174 assert (expected_ml_val ==
175 _table_tester_helper(c, d, extra_args=['--max-width', '42']))
178 @mock.patch('cliff.utils.terminal_width')
179 def test_table_formatter_max_width(tw):
181 c = ('field_name', 'a_really_long_field_name')
182 d = ('the value', 'a value significantly longer than the field')
184 +--------------------------+---------------------------------------------+
186 +--------------------------+---------------------------------------------+
187 | field_name | the value |
188 | a_really_long_field_name | a value significantly longer than the field |
189 +--------------------------+---------------------------------------------+
191 assert expected == _table_tester_helper(c, d)
193 # resize value column
196 +--------------------------+-----------------------------------------+
198 +--------------------------+-----------------------------------------+
199 | field_name | the value |
200 | a_really_long_field_name | a value significantly longer than the |
202 +--------------------------+-----------------------------------------+
204 assert expected == _table_tester_helper(c, d)
206 # resize both columns
209 +-----------------------+------------------------+
211 +-----------------------+------------------------+
212 | field_name | the value |
213 | a_really_long_field_n | a value significantly |
214 | ame | longer than the field |
215 +-----------------------+------------------------+
217 assert expected == _table_tester_helper(c, d)
219 # resize all columns limited by min_width=16
222 +------------------+------------------+
224 +------------------+------------------+
225 | field_name | the value |
226 | a_really_long_fi | a value |
227 | eld_name | significantly |
228 | | longer than the |
230 +------------------+------------------+
232 assert expected == _table_tester_helper(c, d)
235 @mock.patch('cliff.utils.terminal_width')
236 def test_table_list_formatter(tw):
240 d2 = ('D', 'E', 'test\rcarriage\r\nreturn')
243 +---+---+---------------+
245 +---+---+---------------+
247 | D | E | test carriage |
249 +---+---+---------------+
251 assert expected == _table_tester_helper(c, data)
254 @mock.patch('cliff.utils.terminal_width')
255 def test_table_formatter_formattable_column(tw):
257 c = ('a', 'b', 'c', 'd')
258 d = ('A', 'B', 'C', test_columns.FauxColumn(['the', 'value']))
260 +-------+---------------------------------------------+
262 +-------+---------------------------------------------+
266 | d | I made this string myself: ['the', 'value'] |
267 +-------+---------------------------------------------+
269 assert expected == _table_tester_helper(c, d)
272 _col_names = ('one', 'two', 'three')
274 'one one one one one',
280 +---------------------+-----------------+-------------+
281 | one | two | three |
282 +---------------------+-----------------+-------------+
283 | one one one one one | two two two two | three three |
284 +---------------------+-----------------+-------------+
288 +----------------+-----------------+-------------+
289 | one | two | three |
290 +----------------+-----------------+-------------+
291 | one one one | two two two two | three three |
293 +----------------+-----------------+-------------+
297 +---------------+---------------+-------------+
298 | one | two | three |
299 +---------------+---------------+-------------+
300 | one one one | two two two | three three |
302 +---------------+---------------+-------------+
306 +--------------+--------------+-------------+
307 | one | two | three |
308 +--------------+--------------+-------------+
309 | one one one | two two two | three three |
311 +--------------+--------------+-------------+
315 +------------+------------+------------+
316 | one | two | three |
317 +------------+------------+------------+
318 | one one | two two | three |
319 | one one | two two | three |
321 +------------+------------+------------+
325 +----------+----------+----------+
326 | one | two | three |
327 +----------+----------+----------+
328 | one one | two two | three |
329 | one one | two two | three |
331 +----------+----------+----------+
336 @mock.patch('cliff.utils.terminal_width')
337 def test_table_list_formatter_formattable_column(tw):
340 d1 = ('A', 'B', test_columns.FauxColumn(['the', 'value']))
343 +---+---+---------------------------------------------+
345 +---+---+---------------------------------------------+
346 | A | B | I made this string myself: ['the', 'value'] |
347 +---+---+---------------------------------------------+
349 assert expected == _table_tester_helper(c, data)
352 @mock.patch('cliff.utils.terminal_width')
353 def test_table_list_formatter_max_width(tw):
355 l = tw.return_value = 80
356 assert _expected_mv[l] == _table_tester_helper(_col_names, _col_data)
359 l = tw.return_value = 50
360 actual = _table_tester_helper(_col_names, _col_data)
361 assert _expected_mv[l] == actual
362 assert len(actual.splitlines()[0]) == l
365 l = tw.return_value = 45
366 actual = _table_tester_helper(_col_names, _col_data)
367 assert _expected_mv[l] == actual
368 assert len(actual.splitlines()[0]) == l
371 l = tw.return_value = 40
372 actual = _table_tester_helper(_col_names, _col_data)
373 assert _expected_mv[l] == actual
374 assert len(actual.splitlines()[0]) == l
376 # resize all columns limited by min_width=8
377 l = tw.return_value = 10
378 actual = _table_tester_helper(_col_names, _col_data)
379 assert _expected_mv[l] == actual
380 # 3 columns each 8 wide, plus table spacing and borders
381 expected_width = 11 * 3 + 1
382 assert len(actual.splitlines()[0]) == expected_width
385 # Force a wide terminal by overriding its width with envvar
386 @mock.patch('cliff.utils.terminal_width')
387 @mock.patch.dict(os.environ, {'CLIFF_MAX_TERM_WIDTH': '666'})
388 def test_table_list_formatter_max_width_and_envvar_max(tw):
391 assert _expected_mv[80] == _table_tester_helper(_col_names, _col_data)
395 assert _expected_mv[80] == _table_tester_helper(_col_names, _col_data)
399 assert _expected_mv[80] == _table_tester_helper(_col_names, _col_data)
403 assert _expected_mv[80] == _table_tester_helper(_col_names, _col_data)
405 # resize all columns limited by min_width=8
407 assert _expected_mv[80] == _table_tester_helper(_col_names, _col_data)
410 # Force a narrow terminal by overriding its width with envvar
411 @mock.patch('cliff.utils.terminal_width')
412 @mock.patch.dict(os.environ, {'CLIFF_MAX_TERM_WIDTH': '47'})
413 def test_table_list_formatter_max_width_and_envvar_mid(tw):
416 assert _expected_mv[47] == _table_tester_helper(_col_names, _col_data)
420 actual = _table_tester_helper(_col_names, _col_data)
421 assert _expected_mv[47] == actual
422 assert len(actual.splitlines()[0]) == 47
426 actual = _table_tester_helper(_col_names, _col_data)
427 assert _expected_mv[47] == actual
428 assert len(actual.splitlines()[0]) == 47
432 actual = _table_tester_helper(_col_names, _col_data)
433 assert _expected_mv[47] == actual
434 assert len(actual.splitlines()[0]) == 47
436 # resize all columns limited by min_width=8
438 actual = _table_tester_helper(_col_names, _col_data)
439 assert _expected_mv[47] == actual
440 assert len(actual.splitlines()[0]) == 47
443 @mock.patch.dict(os.environ, {'CLIFF_MAX_TERM_WIDTH': '80'})
444 def test_table_list_formatter_env_maxwidth_noresize():
446 assert _expected_mv[80] == _table_tester_helper(_col_names, _col_data)
449 @mock.patch.dict(os.environ, {'CLIFF_MAX_TERM_WIDTH': '50'})
450 def test_table_list_formatter_env_maxwidth_resize_one():
452 actual = _table_tester_helper(_col_names, _col_data)
453 assert _expected_mv[50] == actual
454 assert len(actual.splitlines()[0]) == 50
457 @mock.patch.dict(os.environ, {'CLIFF_MAX_TERM_WIDTH': '45'})
458 def test_table_list_formatter_env_maxwidth_resize_two():
460 actual = _table_tester_helper(_col_names, _col_data)
461 assert _expected_mv[45] == actual
462 assert len(actual.splitlines()[0]) == 45
465 @mock.patch.dict(os.environ, {'CLIFF_MAX_TERM_WIDTH': '40'})
466 def test_table_list_formatter_env_maxwidth_resize_all():
468 actual = _table_tester_helper(_col_names, _col_data)
469 assert _expected_mv[40] == actual
470 assert len(actual.splitlines()[0]) == 40
473 @mock.patch.dict(os.environ, {'CLIFF_MAX_TERM_WIDTH': '8'})
474 def test_table_list_formatter_env_maxwidth_resize_all_tiny():
475 # resize all columns limited by min_width=8
476 actual = _table_tester_helper(_col_names, _col_data)
477 assert _expected_mv[10] == actual
478 # 3 columns each 8 wide, plus table spacing and borders
479 expected_width = 11 * 3 + 1
480 assert len(actual.splitlines()[0]) == expected_width
483 @mock.patch.dict(os.environ, {'CLIFF_MAX_TERM_WIDTH': '42'})
484 def test_table_list_formatter_env_maxwidth_args_big():
485 assert _expected_mv[80] == _table_tester_helper(_col_names, _col_data,
486 extra_args=args(666))
489 @mock.patch.dict(os.environ, {'CLIFF_MAX_TERM_WIDTH': '42'})
490 def test_table_list_formatter_env_maxwidth_args_tiny():
491 assert _expected_mv[40] == _table_tester_helper(_col_names, _col_data,
495 @mock.patch('cliff.utils.terminal_width')
496 def test_table_list_formatter_empty(tw):
501 assert expected == _table_tester_helper(c, data)
504 @mock.patch('cliff.utils.terminal_width')
505 def test_table_list_formatter_empty_table(tw):
515 assert expected == _table_tester_helper(c, data,
516 extra_args=['--print-empty'])
519 def test_field_widths():
520 tf = table.TableFormatter
526 } == tf._field_widths(
527 ('a', 'b', 'c', 'd'),
528 '+---+----+-----+------------+')
531 def test_field_widths_zero():
532 tf = table.TableFormatter
537 } == tf._field_widths(
542 def test_width_info():
543 tf = table.TableFormatter
544 assert (49, 4) == (tf._width_info(80, 10))
545 assert (76, 76) == (tf._width_info(80, 1))
546 assert (79, 0) == (tf._width_info(80, 0))
547 assert (0, 0) == (tf._width_info(0, 80))