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