107
103
def test_progress_construction(self):
108
104
"""TextUIFactory constructs the right progress view.
110
os.environ['BZR_PROGRESS_BAR'] = 'none'
111
self.assertIsInstance(TextUIFactory()._progress_view,
114
os.environ['BZR_PROGRESS_BAR'] = 'text'
115
self.assertIsInstance(TextUIFactory()._progress_view,
118
os.environ['BZR_PROGRESS_BAR'] = 'text'
119
self.assertIsInstance(TextUIFactory()._progress_view,
122
del os.environ['BZR_PROGRESS_BAR']
123
self.assertIsInstance(TextUIFactory()._progress_view,
106
for (file_class, term, pb, expected_pb_class) in (
107
# on an xterm, either use them or not as the user requests,
108
# otherwise default on
109
(_TTYStringIO, 'xterm', 'none', NullProgressView),
110
(_TTYStringIO, 'xterm', 'text', TextProgressView),
111
(_TTYStringIO, 'xterm', None, TextProgressView),
112
# on a dumb terminal, again if there's explicit configuration do
113
# it, otherwise default off
114
(_TTYStringIO, 'dumb', 'none', NullProgressView),
115
(_TTYStringIO, 'dumb', 'text', TextProgressView),
116
(_TTYStringIO, 'dumb', None, NullProgressView),
117
# on a non-tty terminal, it's null regardless of $TERM
118
(StringIO, 'xterm', None, NullProgressView),
119
(StringIO, 'dumb', None, NullProgressView),
120
# however, it can still be forced on
121
(StringIO, 'dumb', 'text', TextProgressView),
123
os.environ['TERM'] = term
125
if 'BZR_PROGRESS_BAR' in os.environ:
126
del os.environ['BZR_PROGRESS_BAR']
128
os.environ['BZR_PROGRESS_BAR'] = pb
129
stdin = file_class('')
130
stderr = file_class()
131
stdout = file_class()
132
uif = make_ui_for_terminal(stdin, stdout, stderr)
133
self.assertIsInstance(uif, TextUIFactory,
134
"TERM=%s BZR_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
135
self.assertIsInstance(uif.make_progress_view(),
137
"TERM=%s BZR_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
139
def test_text_ui_non_terminal(self):
140
"""Even on non-ttys, make_ui_for_terminal gives a text ui."""
141
stdin = _NonTTYStringIO('')
142
stderr = _NonTTYStringIO()
143
stdout = _NonTTYStringIO()
144
for term_type in ['dumb', None, 'xterm']:
145
if term_type is None:
146
del os.environ['TERM']
148
os.environ['TERM'] = term_type
149
uif = make_ui_for_terminal(stdin, stdout, stderr)
150
self.assertIsInstance(uif, TextUIFactory,
151
'TERM=%r' % (term_type,))
126
153
def test_progress_note(self):
127
154
stderr = StringIO()
181
def assert_get_bool_acceptance_of_user_input(self, factory):
182
factory.stdin = StringIO("y\nyes with garbage\n"
183
"yes\nn\nnot an answer\n"
185
factory.stdout = StringIO()
186
factory.stderr = StringIO()
187
# there is no output from the base factory
188
self.assertEqual(True, factory.get_boolean(""))
189
self.assertEqual(True, factory.get_boolean(""))
190
self.assertEqual(False, factory.get_boolean(""))
209
def test_text_ui_get_boolean(self):
210
stdin = StringIO("y\n" # True
212
"yes with garbage\nY\n" # True
213
"not an answer\nno\n" # False
214
"I'm sure!\nyes\n" # True
219
factory = TextUIFactory(stdin, stdout, stderr)
220
self.assertEqual(True, factory.get_boolean(""))
221
self.assertEqual(False, factory.get_boolean(""))
222
self.assertEqual(True, factory.get_boolean(""))
223
self.assertEqual(False, factory.get_boolean(""))
224
self.assertEqual(True, factory.get_boolean(""))
191
225
self.assertEqual(False, factory.get_boolean(""))
192
226
self.assertEqual("foo\n", factory.stdin.read())
193
227
# stdin should be empty
194
228
self.assertEqual('', factory.stdin.readline())
196
def test_silent_ui_getbool(self):
197
factory = SilentUIFactory()
198
self.assert_get_bool_acceptance_of_user_input(factory)
200
def test_silent_factory_prompts_silently(self):
201
factory = SilentUIFactory()
203
factory.stdin = StringIO("y\n")
204
self.assertEqual(True,
205
self.apply_redirected(None, stdout, stdout,
206
factory.get_boolean, "foo"))
207
self.assertEqual("", stdout.getvalue())
208
# stdin should be empty
209
self.assertEqual('', factory.stdin.readline())
211
def test_text_ui_getbool(self):
212
factory = TextUIFactory(None, None, None)
213
self.assert_get_bool_acceptance_of_user_input(factory)
215
230
def test_text_factory_prompt(self):
216
231
# see <https://launchpad.net/bugs/365891>
217
factory = TextUIFactory(None, StringIO(), StringIO(), StringIO())
232
factory = TextUIFactory(StringIO(), StringIO(), StringIO())
218
233
factory.prompt('foo %2e')
219
234
self.assertEqual('', factory.stdout.getvalue())
220
235
self.assertEqual('foo %2e', factory.stderr.getvalue())
298
class TestTextProgressView(TestCase):
299
"""Tests for text display of progress bars.
301
# XXX: These might be a bit easier to write if the rendering and
302
# state-maintaining parts of TextProgressView were more separate, and if
303
# the progress task called back directly to its own view not to the ui
304
# factory. -- mbp 20090312
304
class CLIUITests(TestCase):
306
def test_cli_factory_deprecated(self):
307
uif = self.applyDeprecated(deprecated_in((1, 18, 0)),
309
StringIO(), StringIO(), StringIO())
310
self.assertIsInstance(uif, UIFactory)
313
class SilentUITests(TestCase):
315
def test_silent_factory_get_password(self):
316
# A silent factory that can't do user interaction can't get a
317
# password. Possibly it should raise a more specific error but it
319
ui = SilentUIFactory()
323
self.apply_redirected,
324
None, stdout, stdout, ui.get_password)
325
# and it didn't write anything out either
326
self.assertEqual('', stdout.getvalue())
328
def test_silent_ui_getbool(self):
329
factory = SilentUIFactory()
333
self.apply_redirected,
334
None, stdout, stdout, factory.get_boolean, "foo")
337
class TestUIFactoryTests(TestCase):
339
def test_test_ui_factory_progress(self):
340
# there's no output; we just want to make sure this doesn't crash -
341
# see https://bugs.edge.launchpad.net/bzr/+bug/408201
343
pb = ui.nested_progress_bar()
349
class CannedInputUIFactoryTests(TestCase):
306
def _make_factory(self):
308
uif = TextUIFactory(stderr=out)
309
uif._progress_view._width = 80
312
def test_render_progress_easy(self):
313
"""Just one task and one quarter done"""
314
out, uif = self._make_factory()
315
task = uif.nested_progress_bar()
316
task.update('reticulating splines', 5, 20)
318
'\r[####/ ] reticulating splines 5/20 \r'
321
def test_render_progress_nested(self):
322
"""Tasks proportionally contribute to overall progress"""
323
out, uif = self._make_factory()
324
task = uif.nested_progress_bar()
325
task.update('reticulating splines', 0, 2)
326
task2 = uif.nested_progress_bar()
327
task2.update('stage2', 1, 2)
328
# so we're in the first half of the main task, and half way through
331
r'[####\ ] reticulating splines:stage2 1/2'
332
, uif._progress_view._render_line())
333
# if the nested task is complete, then we're all the way through the
334
# first half of the overall work
335
task2.update('stage2', 2, 2)
337
r'[#########| ] reticulating splines:stage2 2/2'
338
, uif._progress_view._render_line())
340
def test_render_progress_sub_nested(self):
341
"""Intermediate tasks don't mess up calculation."""
342
out, uif = self._make_factory()
343
task_a = uif.nested_progress_bar()
344
task_a.update('a', 0, 2)
345
task_b = uif.nested_progress_bar()
347
task_c = uif.nested_progress_bar()
348
task_c.update('c', 1, 2)
349
# the top-level task is in its first half; the middle one has no
350
# progress indication, just a label; and the bottom one is half done,
351
# so the overall fraction is 1/4
353
r'[####| ] a:b:c 1/2'
354
, uif._progress_view._render_line())
351
def test_canned_input_get_input(self):
352
uif = CannedInputUIFactory([True, 'mbp', 'password'])
353
self.assertEqual(uif.get_boolean('Extra cheese?'), True)
354
self.assertEqual(uif.get_username('Enter your user name'), 'mbp')
355
self.assertEqual(uif.get_password('Password for %(host)s', host='example.com'),
359
class TestBoolFromString(tests.TestCase):
361
def assertIsTrue(self, s, accepted_values=None):
362
res = _mod_ui.bool_from_string(s, accepted_values=accepted_values)
363
self.assertEquals(True, res)
365
def assertIsFalse(self, s, accepted_values=None):
366
res = _mod_ui.bool_from_string(s, accepted_values=accepted_values)
367
self.assertEquals(False, res)
369
def assertIsNone(self, s, accepted_values=None):
370
res = _mod_ui.bool_from_string(s, accepted_values=accepted_values)
371
self.assertIs(None, res)
373
def test_know_valid_values(self):
374
self.assertIsTrue('true')
375
self.assertIsFalse('false')
376
self.assertIsTrue('1')
377
self.assertIsFalse('0')
378
self.assertIsTrue('on')
379
self.assertIsFalse('off')
380
self.assertIsTrue('yes')
381
self.assertIsFalse('no')
382
self.assertIsTrue('y')
383
self.assertIsFalse('n')
384
# Also try some case variations
385
self.assertIsTrue('True')
386
self.assertIsFalse('False')
387
self.assertIsTrue('On')
388
self.assertIsFalse('Off')
389
self.assertIsTrue('ON')
390
self.assertIsFalse('OFF')
391
self.assertIsTrue('oN')
392
self.assertIsFalse('oFf')
394
def test_invalid_values(self):
395
self.assertIsNone(None)
396
self.assertIsNone('doubt')
397
self.assertIsNone('frue')
398
self.assertIsNone('talse')
399
self.assertIsNone('42')
401
def test_provided_values(self):
402
av = dict(y=True, n=False, yes=True, no=False)
403
self.assertIsTrue('y', av)
404
self.assertIsTrue('Y', av)
405
self.assertIsTrue('Yes', av)
406
self.assertIsFalse('n', av)
407
self.assertIsFalse('N', av)
408
self.assertIsFalse('No', av)
409
self.assertIsNone('1', av)
410
self.assertIsNone('0', av)
411
self.assertIsNone('on', av)
412
self.assertIsNone('off', av)