[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [nyx/master] Revise descriptor dialog
commit cfaf6953c5a2df4521fb48e464b8415b594d4a11
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date: Mon Apr 4 15:36:14 2016 -0700
Revise descriptor dialog
Definitely the largest, thorniest in this file. Rejiggered code, migrating to
the new draw() function and adding tests.
---
nyx/curses.py | 69 ++++++++++++++++++--
nyx/panel/connection.py | 8 +--
nyx/panel/graph.py | 4 +-
nyx/panel/log.py | 2 +-
nyx/popups.py | 170 ++++++++++++++++++++----------------------------
test/popups.py | 119 +++++++++++++++++++++++++--------
6 files changed, 232 insertions(+), 140 deletions(-)
diff --git a/nyx/curses.py b/nyx/curses.py
index 6d3b170..3718742 100644
--- a/nyx/curses.py
+++ b/nyx/curses.py
@@ -15,6 +15,7 @@ if we want Windows support in the future too.
raw_screen - provides direct access to the curses screen
key_input - get keypress by user
curses_attr - curses encoded text attribute
+ screen_size - provides the dimensions of our screen
screenshot - dump of the present on-screen content
is_color_supported - checks if terminal supports color output
@@ -76,11 +77,13 @@ if we want Windows support in the future too.
from __future__ import absolute_import
+import collections
import curses
import threading
import stem.util.conf
import stem.util.enum
+import stem.util.str_tools
import stem.util.system
from nyx import msg, log
@@ -135,16 +138,21 @@ SPECIAL_KEYS = {
'esc': 27,
}
+Dimensions = collections.namedtuple('Dimensions', ['width', 'height'])
+
def conf_handler(key, value):
if key == 'features.colorOverride':
if value not in Color and value != 'None':
raise ValueError(msg('usage.unable_to_set_color_override', color = value))
+ elif key == 'features.torrc.maxLineWrap':
+ return max(1, value)
CONFIG = stem.util.conf.config_dict('nyx', {
'features.colorOverride': 'None',
'features.colorInterface': True,
+ 'features.maxLineWrap': 8,
}, conf_handler)
@@ -251,6 +259,17 @@ def curses_attr(*attributes):
return encoded
+def screen_size():
+ """
+ Provides the current dimensions of our screen.
+
+ :returns: :data:`~nyx.curses.Dimensions` with our screen size
+ """
+
+ height, width = CURSES_SCREEN.getmaxyx()
+ return Dimensions(width, height)
+
+
def screenshot():
"""
Provides a dump of the present content of the screen.
@@ -260,7 +279,7 @@ def screenshot():
lines = []
- for y in range(CURSES_SCREEN.getmaxyx()[0]):
+ for y in range(screen_size().height):
lines.append(CURSES_SCREEN.instr(y, 0).rstrip())
return '\n'.join(lines).rstrip()
@@ -408,10 +427,9 @@ def draw(func, left = 0, top = 0, width = None, height = None):
"""
with CURSES_LOCK:
- max_height, max_width = CURSES_SCREEN.getmaxyx()
-
- subwindow_width = max(0, max_width - left)
- subwindow_height = max(0, max_height - top)
+ dimensions = screen_size()
+ subwindow_width = max(0, dimensions.width - left)
+ subwindow_height = max(0, dimensions.height - top)
if width:
subwindow_width = min(width, subwindow_width)
@@ -443,7 +461,7 @@ class _Subwindow(object):
Draws a string in the subwindow.
:param int x: horizontal location
- :param int y, vertical location
+ :param int y: vertical location
:param str msg: string to be written
:param list attr: text attributes to apply
"""
@@ -458,6 +476,36 @@ class _Subwindow(object):
return x
+ def addstr_wrap(self, x, y, msg, width, min_x = 0, *attr):
+ """
+ Draws a string in the subwindow, with text wrapped if it exceeds a width.
+
+ :param int x: horizontal location
+ :param int y: vertical location
+ :param str msg: string to be written
+ :param int width: width avaialble to render the string
+ :param int min_x: horizontal position to wrap to on new lines
+ :param list attr: text attributes to apply
+ """
+
+ orig_y = y
+
+ while msg:
+ draw_msg, msg = stem.util.str_tools.crop(msg, width - x, None, ending = None, get_remainder = True)
+
+ if not draw_msg:
+ draw_msg, msg = stem.util.str_tools.crop(msg, width - x), '' # first word is longer than the line
+
+ x = self.addstr(x, y, draw_msg, *attr)
+
+ if (y - orig_y + 1) >= CONFIG['features.maxLineWrap']:
+ break # maximum number we'll wrap
+
+ if msg:
+ x, y = min_x, y + 1
+
+ return x, y
+
def box(self, left = 0, top = 0, width = None, height = None, *attr):
"""
Draws a box with the given bounds.
@@ -551,6 +599,15 @@ class KeyInput(object):
return self._key in (curses.KEY_ENTER, 10, ord(' '))
+ def __eq__(self, other):
+ if isinstance(other, KeyInput):
+ return self._key == other._key
+ else:
+ return False
+
+ def __ne__(self, other):
+ return not self == other
+
class Scroller(object):
"""
diff --git a/nyx/panel/connection.py b/nyx/panel/connection.py
index e8eb0b5..afd1da1 100644
--- a/nyx/panel/connection.py
+++ b/nyx/panel/connection.py
@@ -376,14 +376,14 @@ class ConnectionPanel(nyx.panel.Panel, threading.Thread):
return key.is_selection() or key.match('d') or key.match('left') or key.match('right')
color = CONFIG['attr.connection.category_color'].get(selected.entry.get_type(), WHITE)
- key = nyx.popups.show_descriptor_popup(selected.fingerprint, color, self.max_x, is_close_key)
+ key = nyx.popups.show_descriptor(selected.fingerprint, color, is_close_key)
if not key or key.is_selection() or key.match('d'):
break # closes popup
elif key.match('left'):
- self.handle_key(nyx.curses.KeyInput(curses.KEY_UP))
+ _scroll(nyx.curses.KeyInput(curses.KEY_UP))
elif key.match('right'):
- self.handle_key(nyx.curses.KeyInput(curses.KEY_DOWN))
+ _scroll(nyx.curses.KeyInput(curses.KEY_DOWN))
self.redraw(True)
@@ -392,7 +392,7 @@ class ConnectionPanel(nyx.panel.Panel, threading.Thread):
resolver = connection_tracker.get_custom_resolver()
options = ['auto'] + list(connection.Resolver) + list(nyx.tracker.CustomResolver)
- selected = nyx.popups.show_selector('Connection Resolver:', options, resolver if resolver else 'auto')
+ selected = nyx.popups.show_list_selector('Connection Resolver:', options, resolver if resolver else 'auto')
connection_tracker.set_custom_resolver(None if selected == 'auto' else selected)
self.redraw(True)
diff --git a/nyx/panel/graph.py b/nyx/panel/graph.py
index 2b40390..cad754b 100644
--- a/nyx/panel/graph.py
+++ b/nyx/panel/graph.py
@@ -510,7 +510,7 @@ class GraphPanel(nyx.panel.Panel):
options = ['None'] + [stat.capitalize() for stat in available_stats]
previous_selection = options[available_stats.index(self.displayed_stat) + 1] if self.displayed_stat else 'None'
- selection = nyx.popups.show_selector('Graphed Stats:', options, previous_selection)
+ selection = nyx.popups.show_list_selector('Graphed Stats:', options, previous_selection)
self.displayed_stat = None if selection == 'None' else available_stats[options.index(selection) - 1]
def _next_bounds():
@@ -518,7 +518,7 @@ class GraphPanel(nyx.panel.Panel):
self.redraw(True)
def _pick_interval():
- self.update_interval = nyx.popups.show_selector('Update Interval:', list(Interval), self.update_interval)
+ self.update_interval = nyx.popups.show_list_selector('Update Interval:', list(Interval), self.update_interval)
self.redraw(True)
return (
diff --git a/nyx/panel/log.py b/nyx/panel/log.py
index 765e251..4582885 100644
--- a/nyx/panel/log.py
+++ b/nyx/panel/log.py
@@ -237,7 +237,7 @@ class LogPanel(nyx.panel.Panel, threading.Thread):
with nyx.curses.CURSES_LOCK:
options = ['None'] + self._filter.latest_selections() + ['New...']
initial_selection = self._filter.selection() if self._filter.selection() else 'None'
- selection = nyx.popups.show_selector('Log Filter:', options, initial_selection)
+ selection = nyx.popups.show_list_selector('Log Filter:', options, initial_selection)
if selection == 'None':
self._filter.select(None)
diff --git a/nyx/popups.py b/nyx/popups.py
index 261cdce..4bf14fe 100644
--- a/nyx/popups.py
+++ b/nyx/popups.py
@@ -122,7 +122,7 @@ def show_help():
subwindow.addstr(2, 7, 'Press any key...')
with nyx.curses.CURSES_LOCK:
- nyx.curses.draw(_render, top = control.header_panel().get_height(), width = 80, height = 9)
+ nyx.curses.draw(_render, top = _top(), width = 80, height = 9)
keypress = nyx.curses.key_input()
if keypress.is_selection() or keypress.is_scroll() or keypress.match('left', 'right'):
@@ -146,7 +146,7 @@ def show_about():
subwindow.addstr(2, 7, 'Press any key...')
with nyx.curses.CURSES_LOCK:
- nyx.curses.draw(_render, top = nyx.controller.get_controller().header_panel().get_height(), width = 80, height = 9)
+ nyx.curses.draw(_render, top = _top(), width = 80, height = 9)
nyx.curses.key_input()
@@ -188,18 +188,16 @@ def show_counts(title, counts, fill_char = ' '):
subwindow.addstr(2, subwindow.height - 2, 'Press any key...')
- top = nyx.controller.get_controller().header_panel().get_height()
-
with nyx.curses.CURSES_LOCK:
if not counts:
- nyx.curses.draw(_render_no_stats, top = top, width = len(NO_STATS_MSG) + 4, height = 3)
+ nyx.curses.draw(_render_no_stats, top = _top(), width = len(NO_STATS_MSG) + 4, height = 3)
else:
- nyx.curses.draw(_render_stats, top = top, width = 80, height = 4 + max(1, len(counts)))
+ nyx.curses.draw(_render_stats, top = _top(), width = 80, height = 4 + max(1, len(counts)))
nyx.curses.key_input()
-def show_selector(title, options, previous_selection):
+def show_list_selector(title, options, previous_selection):
"""
Provides list of items the user can choose from.
@@ -211,7 +209,6 @@ def show_selector(title, options, previous_selection):
"""
selected_index = options.index(previous_selection) if previous_selection in options else 0
- top = nyx.controller.get_controller().header_panel().get_height()
def _render(subwindow):
subwindow.box()
@@ -226,8 +223,8 @@ def show_selector(title, options, previous_selection):
with nyx.curses.CURSES_LOCK:
while True:
- nyx.curses.draw(lambda subwindow: subwindow.addstr(0, 0, ' ' * 500), top = top, height = 1) # hides title below us
- nyx.curses.draw(_render, top = top, width = max(map(len, options)) + 9, height = len(options) + 2)
+ nyx.curses.draw(lambda subwindow: subwindow.addstr(0, 0, ' ' * 500), top = _top(), height = 1) # hides title below us
+ nyx.curses.draw(_render, top = _top(), width = max(map(len, options)) + 9, height = len(options) + 2)
key = nyx.curses.key_input()
if key.match('up'):
@@ -285,7 +282,7 @@ def show_sort_dialog(title, options, previous_order, option_colors):
with nyx.curses.CURSES_LOCK:
while len(new_order) < len(previous_order):
- nyx.curses.draw(_render, top = nyx.controller.get_controller().header_panel().get_height(), width = 80, height = 9)
+ nyx.curses.draw(_render, top = _top(), width = 80, height = 9)
key = nyx.curses.key_input()
if key.match('left'):
@@ -311,13 +308,12 @@ def show_sort_dialog(title, options, previous_order, option_colors):
return new_order
-def show_descriptor_popup(fingerprint, color, max_width, is_close_key):
+def show_descriptor(fingerprint, color, is_close_key):
"""
- Provides a dialog showing the descriptors for a given relay.
+ Provides a dialog showing descriptors for a relay.
:param str fingerprint: fingerprint of the relay to be shown
:param str color: text color of the dialog
- :param int max_width: maximum width of the dialog
:param function is_close_key: method to indicate if a key should close the
dialog or not
@@ -326,39 +322,78 @@ def show_descriptor_popup(fingerprint, color, max_width, is_close_key):
"""
if fingerprint:
- title = 'Consensus Descriptor:'
- lines = _display_text(fingerprint)
+ title = 'Consensus Descriptor (%s):' % fingerprint
+ lines = _descriptor_text(fingerprint)
show_line_numbers = True
else:
- title = 'Consensus Descriptor (%s):' % fingerprint
+ title = 'Consensus Descriptor:'
lines = [UNRESOLVED_MSG]
show_line_numbers = False
- popup_height, popup_width = _preferred_size(lines, max_width, show_line_numbers)
+ scroller = nyx.curses.Scroller()
+ line_number_width = int(math.log10(len(lines))) + 1 if show_line_numbers else 0
- with popup_window(popup_height, popup_width) as (popup, _, height):
- if not popup:
- return None
+ def _render(subwindow):
+ in_block = False # flag indicating if we're currently in crypto content
+ y, offset = 1, line_number_width + 3 if show_line_numbers else 2
+
+ for i, line in enumerate(lines):
+ keyword, value = line, ''
+ line_color = color
+
+ if line in HEADERS:
+ line_color = HEADER_COLOR
+ elif line.startswith(BLOCK_START):
+ in_block = True
+ elif line.startswith(BLOCK_END):
+ in_block = False
+ elif in_block:
+ keyword, value = '', line
+ elif ' ' in line and line != UNRESOLVED_MSG and line != ERROR_MSG:
+ keyword, value = line.split(' ', 1)
+ keyword = keyword + ' '
+
+ if i < scroller.location():
+ continue
+
+ if show_line_numbers:
+ subwindow.addstr(2, y, str(i + 1).rjust(line_number_width), LINE_NUMBER_COLOR, BOLD)
+
+ x, y = subwindow.addstr_wrap(3 + line_number_width, y, keyword, subwindow.width - 2, offset, line_color, BOLD)
+ x, y = subwindow.addstr_wrap(x, y, value, subwindow.width - 2, offset, line_color)
+ y += 1
+
+ if y > subwindow.height - 2:
+ break
- with popup_window(1, -1) as (title_erase, _, _):
- title_erase.addstr(0, 0, ' ' * 500) # hide title of the panel below us
+ subwindow.box()
+ subwindow.addstr(0, 0, title, HIGHLIGHT)
- scroller, redraw = nyx.curses.Scroller(), True
+ width, height = 0, len(lines) + 2
+ screen_size = nyx.curses.screen_size()
- while True:
- if redraw:
- _draw(popup, title, lines, color, scroller.location(), show_line_numbers)
- redraw = False
+ for line in lines:
+ width = min(screen_size.width, max(width, len(line) + line_number_width + 5))
+ height += len(line) / (screen_size.width - line_number_width - 5) # extra lines due to text wrap
- key = nyx.curses.key_input()
+ with nyx.curses.CURSES_LOCK:
+ nyx.curses.draw(lambda subwindow: subwindow.addstr(0, 0, ' ' * 500), top = _top(), height = 1) # hides title below us
+ nyx.curses.draw(_render, top = _top(), width = width, height = height)
+ popup_height = min(screen_size.height - _top(), height)
+
+ while True:
+ key = nyx.curses.key_input()
- if key.is_scroll():
- redraw = scroller.handle_key(key, len(lines), height - 2)
- elif is_close_key(key):
- return key
+ if key.is_scroll():
+ is_changed = scroller.handle_key(key, len(lines), popup_height - 2)
+ if is_changed:
+ nyx.curses.draw(_render, top = _top(), width = width, height = height)
+ elif is_close_key(key):
+ return key
-def _display_text(fingerprint):
+
+def _descriptor_text(fingerprint):
"""
Provides the descriptors for a relay.
@@ -383,68 +418,5 @@ def _display_text(fingerprint):
return description.split('\n')
-def _preferred_size(text, max_width, show_line_numbers):
- """
- Provides the preferred dimensions of our dialog.
-
- :param list text: lines of text to be shown
- :param int max_width: maximum width the dialog can be
- :param bool show_line_numbers: if we should leave room for line numbers
-
- :returns: **tuple** of the preferred (height, width)
- """
-
- width, height = 0, len(text) + 2
- line_number_width = int(math.log10(len(text))) + 2 if show_line_numbers else 0
- max_content_width = max_width - line_number_width - 4
-
- for line in text:
- width = min(max_width, max(width, len(line) + line_number_width + 4))
- height += len(line) / max_content_width # extra lines due to text wrap
-
- return (height, width)
-
-
-def _draw(popup, title, lines, entry_color, scroll, show_line_numbers):
- popup.win.erase()
-
- line_number_width = int(math.log10(len(lines))) + 1
- in_block = False # flag indicating if we're currently in crypto content
- width = popup.max_x - 2 # leave space on the right for the border and an empty line
- height = popup.max_y - 2 # height of the dialog without the top and bottom border
- offset = line_number_width + 3 if show_line_numbers else 2
-
- y = 1
-
- for i, line in enumerate(lines):
- keyword, value = line, ''
- color = entry_color
-
- if line in HEADERS:
- color = HEADER_COLOR
- elif line.startswith(BLOCK_START):
- in_block = True
- elif line.startswith(BLOCK_END):
- in_block = False
- elif in_block:
- keyword, value = '', line
- elif ' ' in line and line != UNRESOLVED_MSG and line != ERROR_MSG:
- keyword, value = line.split(' ', 1)
-
- if i < scroll:
- continue
-
- if show_line_numbers:
- popup.addstr(y, 2, str(i + 1).rjust(line_number_width), LINE_NUMBER_COLOR, BOLD)
-
- x, y = popup.addstr_wrap(y, 3 + line_number_width, keyword, width, offset, color, BOLD)
- x, y = popup.addstr_wrap(y, x + 1, value, width, offset, color)
-
- y += 1
-
- if y > height:
- break
-
- popup.draw_box()
- popup.addstr(0, 0, title, HIGHLIGHT)
- popup.win.refresh()
+def _top():
+ return nyx.controller.get_controller().header_panel().get_height()
diff --git a/test/popups.py b/test/popups.py
index f3d4963..2a308f0 100644
--- a/test/popups.py
+++ b/test/popups.py
@@ -53,7 +53,7 @@ Client Locales-----------------------------------------------------------------+
+------------------------------------------------------------------------------+
""".strip()
-EXPECTED_SELECTOR = """
+EXPECTED_LIST_SELECTOR = """
Update Interval:---+
| > each second |
| 5 seconds |
@@ -90,9 +90,72 @@ Config Option Ordering:--------------------------------------------------------+
+------------------------------------------------------------------------------+
""".strip()
+EXPECTED_DESCRIPTOR_WITHOUT_FINGERPRINT = """
+Consensus Descriptor:----------+
+| No consensus data available |
++------------------------------+
+""".strip()
+
+DESCRIPTOR_TEXT = """
+Consensus:
+
+r cyberphunk KXh3YBRc0aRzVSovxkxyqaEwgg4 VjdJThHuYj0jDY2tkkDJkCa8s1s 2016-04-04 19:03:16 94.23.150.191 8080 0
+s Fast Guard Running Stable Valid
+w Bandwidth=8410
+p reject 1-65535
+
+Server Descriptor:
+
+router cyberphunk 94.23.150.191 8080 0 0
+platform Tor 0.2.4.27 on Linux
+protocols Link 1 2 Circuit 1
+published 2016-04-04 19:03:16
+fingerprint 2978 7760 145C D1A4 7355 2A2F C64C 72A9 A130 820E
+uptime 3899791
+bandwidth 10240000 10444800 6482376
+extra-info-digest 9DC532664DDFD238A4119D623D30F136A3B851BF
+reject *:*
+router-signature
+-----BEGIN SIGNATURE-----
+EUFm38gONCoDuY7ZWHyJtBKuvk6Xi1MPuKuecS5frP3fX0wiZSrOVcpX0X8J+4Hr
+Fb5i+yuMIAXeEn6UhtjqhhZBbY9PW9GdZOMTH8hJpG+evURyr+10PZq6UElg86rA
+NCGI042p6+7UgCVT1x3WcLnq3ScV//s1wXHrUXa7vi0=
+-----END SIGNATURE-----
+""".strip().split('\n')
+
+EXPECTED_DESCRIPTOR = """
+Consensus Descriptor (29787760145CD1A473552A2FC64C72A9A130820E):---------------------------------------------------+
+| 1 Consensus: |
+| 2 |
+| 3 r cyberphunk KXh3YBRc0aRzVSovxkxyqaEwgg4 VjdJThHuYj0jDY2tkkDJkCa8s1s 2016-04-04 19:03:16 94.23.150.191 8080 0 |
+| 4 s Fast Guard Running Stable Valid |
+| 5 w Bandwidth=8410 |
+| 6 p reject 1-65535 |
+| 7 |
+| 8 Server Descriptor: |
+| 9 |
+| 10 router cyberphunk 94.23.150.191 8080 0 0 |
+| 11 platform Tor 0.2.4.27 on Linux |
+| 12 protocols Link 1 2 Circuit 1 |
+| 13 published 2016-04-04 19:03:16 |
+| 14 fingerprint 2978 7760 145C D1A4 7355 2A2F C64C 72A9 A130 820E |
+| 15 uptime 3899791 |
+| 16 bandwidth 10240000 10444800 6482376 |
+| 17 extra-info-digest 9DC532664DDFD238A4119D623D30F136A3B851BF |
+| 18 reject *:* |
+| 19 router-signature |
+| 20 -----BEGIN SIGNATURE----- |
+| 21 EUFm38gONCoDuY7ZWHyJtBKuvk6Xi1MPuKuecS5frP3fX0wiZSrOVcpX0X8J+4Hr |
+| 22 Fb5i+yuMIAXeEn6UhtjqhhZBbY9PW9GdZOMTH8hJpG+evURyr+10PZq6UElg86rA |
+| 23 NCGI042p6+7UgCVT1x3WcLnq3ScV//s1wXHrUXa7vi0= |
+| 24 -----END SIGNATURE----- |
++------------------------------------------------------------------------------------------------------------------+
+""".strip()
+
class TestPopups(unittest.TestCase):
@patch('nyx.controller.get_controller')
+ @patch('nyx.popups._top', Mock(return_value = 0))
def test_help(self, get_controller_mock):
header_panel = Mock()
@@ -121,30 +184,23 @@ class TestPopups(unittest.TestCase):
nyx.panel.KeyHandler('c', 'clear event log'),
)
- get_controller_mock().header_panel().get_height.return_value = 0
get_controller_mock().get_display_panels.return_value = [header_panel, graph_panel, log_panel]
rendered = test.render(nyx.popups.show_help)
self.assertEqual(EXPECTED_HELP_POPUP, rendered.content)
- @patch('nyx.controller.get_controller')
- def test_about(self, get_controller_mock):
- get_controller_mock().header_panel().get_height.return_value = 0
-
+ @patch('nyx.popups._top', Mock(return_value = 0))
+ def test_about(self):
rendered = test.render(nyx.popups.show_about)
self.assertEqual(EXPECTED_ABOUT_POPUP, rendered.content)
- @patch('nyx.controller.get_controller')
- def test_counts_when_empty(self, get_controller_mock):
- get_controller_mock().header_panel().get_height.return_value = 0
-
+ @patch('nyx.popups._top', Mock(return_value = 0))
+ def test_counts_when_empty(self):
rendered = test.render(nyx.popups.show_counts, 'Client Locales', {})
self.assertEqual(EXPECTED_EMPTY_COUNTS, rendered.content)
- @patch('nyx.controller.get_controller')
- def test_counts(self, get_controller_mock):
- get_controller_mock().header_panel().get_height.return_value = 0
-
+ @patch('nyx.popups._top', Mock(return_value = 0))
+ def test_counts(self):
clients = {
'fr': 5,
'us': 6,
@@ -156,19 +212,15 @@ class TestPopups(unittest.TestCase):
rendered = test.render(nyx.popups.show_counts, 'Client Locales', clients, fill_char = '*')
self.assertEqual(EXPECTED_COUNTS, rendered.content)
- @patch('nyx.controller.get_controller')
- def test_selector(self, get_controller_mock):
- get_controller_mock().header_panel().get_height.return_value = 0
-
+ @patch('nyx.popups._top', Mock(return_value = 0))
+ def test_selector(self):
options = ['each second', '5 seconds', '30 seconds', 'minutely', '15 minute', '30 minute', 'hourly', 'daily']
- rendered = test.render(nyx.popups.show_selector, 'Update Interval:', options, 'each second')
- self.assertEqual(EXPECTED_SELECTOR, rendered.content)
+ rendered = test.render(nyx.popups.show_list_selector, 'Update Interval:', options, 'each second')
+ self.assertEqual(EXPECTED_LIST_SELECTOR, rendered.content)
self.assertEqual('each second', rendered.return_value)
- @patch('nyx.controller.get_controller')
- def test_sort_dialog(self, get_controller_mock):
- get_controller_mock().header_panel().get_height.return_value = 0
-
+ @patch('nyx.popups._top', Mock(return_value = 0))
+ def test_sort_dialog(self):
previous_order = ['Man Page Entry', 'Name', 'Is Set']
options = ['Name', 'Value', 'Value Type', 'Category', 'Usage', 'Summary', 'Description', 'Man Page Entry', 'Is Set']
@@ -176,8 +228,8 @@ class TestPopups(unittest.TestCase):
self.assertEqual(EXPECTED_SORT_DIALOG_START, rendered.content)
self.assertEqual(None, rendered.return_value)
- @patch('nyx.controller.get_controller')
- def test_sort_dialog_selecting(self, get_controller_mock):
+ @patch('nyx.popups._top', Mock(return_value = 0))
+ def test_sort_dialog_selecting(self):
# Use the dialog to make a selection. At the end we render two options as
# being selected (rather than three) because the act of selecing the third
# closed the popup.
@@ -193,11 +245,22 @@ class TestPopups(unittest.TestCase):
with patch('nyx.curses.key_input', side_effect = keypresses):
return nyx.popups.show_sort_dialog('Config Option Ordering:', options, previous_order, {})
- get_controller_mock().header_panel().get_height.return_value = 0
-
previous_order = ['Man Page Entry', 'Name', 'Is Set']
options = ['Name', 'Value', 'Value Type', 'Category', 'Usage', 'Summary', 'Description', 'Man Page Entry', 'Is Set']
rendered = test.render(draw_func)
self.assertEqual(EXPECTED_SORT_DIALOG_END, rendered.content)
self.assertEqual(['Name', 'Summary', 'Description'], rendered.return_value)
+
+ @patch('nyx.popups._top', Mock(return_value = 0))
+ def test_descriptor_without_fingerprint(self):
+ rendered = test.render(nyx.popups.show_descriptor, None, nyx.curses.Color.RED, lambda key: key.match('esc'))
+ self.assertEqual(EXPECTED_DESCRIPTOR_WITHOUT_FINGERPRINT, rendered.content)
+ self.assertEqual(nyx.curses.KeyInput(27), rendered.return_value)
+
+ @patch('nyx.popups._top', Mock(return_value = 0))
+ @patch('nyx.popups._descriptor_text', Mock(return_value = DESCRIPTOR_TEXT))
+ def test_descriptor(self):
+ rendered = test.render(nyx.popups.show_descriptor, '29787760145CD1A473552A2FC64C72A9A130820E', nyx.curses.Color.RED, lambda key: key.match('esc'))
+ self.assertEqual(EXPECTED_DESCRIPTOR, rendered.content)
+ self.assertEqual(nyx.curses.KeyInput(27), rendered.return_value)
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits