1# -*- coding: utf-8 -*- 2"""Automated tests (as opposed to human-verified test patterns) 3 4It was tempting to mock out curses to get predictable output from ``tigetstr``, 5but there are concrete integration-testing benefits in not doing so. For 6instance, ``tigetstr`` changed its return type in Python 3.2.3. So instead, we 7simply create all our test ``Terminal`` instances with a known terminal type. 8All we require from the host machine is that a standard terminfo definition of 9xterm-256color exists. 10 11""" 12from __future__ import with_statement # Make 2.5-compatible 13from curses import tigetstr, tparm 14from functools import partial 15from StringIO import StringIO 16import sys 17 18from nose import SkipTest 19from nose.tools import eq_ 20 21# This tests that __all__ is correct, since we use below everything that should 22# be imported: 23from blessings import * 24 25 26TestTerminal = partial(Terminal, kind='xterm-256color') 27 28 29def unicode_cap(cap): 30 """Return the result of ``tigetstr`` except as Unicode.""" 31 return tigetstr(cap).decode('utf-8') 32 33 34def unicode_parm(cap, *parms): 35 """Return the result of ``tparm(tigetstr())`` except as Unicode.""" 36 return tparm(tigetstr(cap), *parms).decode('utf-8') 37 38 39def test_capability(): 40 """Check that a capability lookup works. 41 42 Also test that Terminal grabs a reasonable default stream. This test 43 assumes it will be run from a tty. 44 45 """ 46 t = TestTerminal() 47 sc = unicode_cap('sc') 48 eq_(t.save, sc) 49 eq_(t.save, sc) # Make sure caching doesn't screw it up. 50 51 52def test_capability_without_tty(): 53 """Assert capability templates are '' when stream is not a tty.""" 54 t = TestTerminal(stream=StringIO()) 55 eq_(t.save, u'') 56 eq_(t.red, u'') 57 58 59def test_capability_with_forced_tty(): 60 """If we force styling, capabilities had better not (generally) be empty.""" 61 t = TestTerminal(stream=StringIO(), force_styling=True) 62 eq_(t.save, unicode_cap('sc')) 63 64 65def test_parametrization(): 66 """Test parametrizing a capability.""" 67 eq_(TestTerminal().cup(3, 4), unicode_parm('cup', 3, 4)) 68 69 70def height_and_width(): 71 """Assert that ``height_and_width()`` returns ints.""" 72 t = TestTerminal() # kind shouldn't matter. 73 assert isinstance(int, t.height) 74 assert isinstance(int, t.width) 75 76 77def test_stream_attr(): 78 """Make sure Terminal exposes a ``stream`` attribute that defaults to something sane.""" 79 eq_(Terminal().stream, sys.__stdout__) 80 81 82def test_location(): 83 """Make sure ``location()`` does what it claims.""" 84 t = TestTerminal(stream=StringIO(), force_styling=True) 85 86 with t.location(3, 4): 87 t.stream.write(u'hi') 88 89 eq_(t.stream.getvalue(), unicode_cap('sc') + 90 unicode_parm('cup', 4, 3) + 91 u'hi' + 92 unicode_cap('rc')) 93 94 95def test_horizontal_location(): 96 """Make sure we can move the cursor horizontally without changing rows.""" 97 t = TestTerminal(stream=StringIO(), force_styling=True) 98 with t.location(x=5): 99 pass 100 eq_(t.stream.getvalue(), unicode_cap('sc') + 101 unicode_parm('hpa', 5) + 102 unicode_cap('rc')) 103 104 105def test_null_fileno(): 106 """Make sure ``Terminal`` works when ``fileno`` is ``None``. 107 108 This simulates piping output to another program. 109 110 """ 111 out = StringIO() 112 out.fileno = None 113 t = TestTerminal(stream=out) 114 eq_(t.save, u'') 115 116 117def test_mnemonic_colors(): 118 """Make sure color shortcuts work.""" 119 def color(num): 120 return unicode_parm('setaf', num) 121 122 def on_color(num): 123 return unicode_parm('setab', num) 124 125 # Avoid testing red, blue, yellow, and cyan, since they might someday 126 # change depending on terminal type. 127 t = TestTerminal() 128 eq_(t.white, color(7)) 129 eq_(t.green, color(2)) # Make sure it's different than white. 130 eq_(t.on_black, on_color(0)) 131 eq_(t.on_green, on_color(2)) 132 eq_(t.bright_black, color(8)) 133 eq_(t.bright_green, color(10)) 134 eq_(t.on_bright_black, on_color(8)) 135 eq_(t.on_bright_green, on_color(10)) 136 137 138def test_callable_numeric_colors(): 139 """``color(n)`` should return a formatting wrapper.""" 140 t = TestTerminal() 141 eq_(t.color(5)('smoo'), t.magenta + 'smoo' + t.normal) 142 eq_(t.color(5)('smoo'), t.color(5) + 'smoo' + t.normal) 143 eq_(t.on_color(2)('smoo'), t.on_green + 'smoo' + t.normal) 144 eq_(t.on_color(2)('smoo'), t.on_color(2) + 'smoo' + t.normal) 145 146 147def test_null_callable_numeric_colors(): 148 """``color(n)`` should be a no-op on null terminals.""" 149 t = TestTerminal(stream=StringIO()) 150 eq_(t.color(5)('smoo'), 'smoo') 151 eq_(t.on_color(6)('smoo'), 'smoo') 152 153 154def test_naked_color_cap(): 155 """``term.color`` should return a stringlike capability.""" 156 t = TestTerminal() 157 eq_(t.color + '', t.setaf + '') 158 159 160def test_number_of_colors_without_tty(): 161 """``number_of_colors`` should return 0 when there's no tty.""" 162 # Hypothesis: once setupterm() has run and decided the tty supports 256 163 # colors, it never changes its mind. 164 raise SkipTest 165 166 t = TestTerminal(stream=StringIO()) 167 eq_(t.number_of_colors, 0) 168 t = TestTerminal(stream=StringIO(), force_styling=True) 169 eq_(t.number_of_colors, 0) 170 171 172def test_number_of_colors_with_tty(): 173 """``number_of_colors`` should work.""" 174 t = TestTerminal() 175 eq_(t.number_of_colors, 256) 176 177 178def test_formatting_functions(): 179 """Test crazy-ass formatting wrappers, both simple and compound.""" 180 t = TestTerminal() 181 # By now, it should be safe to use sugared attributes. Other tests test those. 182 eq_(t.bold(u'hi'), t.bold + u'hi' + t.normal) 183 eq_(t.green('hi'), t.green + u'hi' + t.normal) # Plain strs for Python 2.x 184 # Test some non-ASCII chars, probably not necessary: 185 eq_(t.bold_green(u'boö'), t.bold + t.green + u'boö' + t.normal) 186 eq_(t.bold_underline_green_on_red('boo'), 187 t.bold + t.underline + t.green + t.on_red + u'boo' + t.normal) 188 # Don't spell things like this: 189 eq_(t.on_bright_red_bold_bright_green_underline('meh'), 190 t.on_bright_red + t.bold + t.bright_green + t.underline + u'meh' + t.normal) 191 192 193def test_formatting_functions_without_tty(): 194 """Test crazy-ass formatting wrappers when there's no tty.""" 195 t = TestTerminal(stream=StringIO()) 196 eq_(t.bold(u'hi'), u'hi') 197 eq_(t.green('hi'), u'hi') 198 # Test non-ASCII chars, no longer really necessary: 199 eq_(t.bold_green(u'boö'), u'boö') 200 eq_(t.bold_underline_green_on_red('loo'), u'loo') 201 eq_(t.on_bright_red_bold_bright_green_underline('meh'), u'meh') 202 203 204def test_nice_formatting_errors(): 205 """Make sure you get nice hints if you misspell a formatting wrapper.""" 206 t = TestTerminal() 207 try: 208 t.bold_misspelled('hey') 209 except TypeError, e: 210 assert 'probably misspelled' in e.args[0] 211 212 try: 213 t.bold_misspelled(u'hey') # unicode 214 except TypeError, e: 215 assert 'probably misspelled' in e.args[0] 216 217 try: 218 t.bold_misspelled(None) # an arbitrary non-string 219 except TypeError, e: 220 assert 'probably misspelled' not in e.args[0] 221 222 try: 223 t.bold_misspelled('a', 'b') # >1 string arg 224 except TypeError, e: 225 assert 'probably misspelled' not in e.args[0] 226 227 228def test_init_descriptor_always_initted(): 229 """We should be able to get a height and width even on no-tty Terminals.""" 230 t = Terminal(stream=StringIO()) 231 eq_(type(t.height), int) 232