Raise NotImplemetedError.
This commit is contained in:
@@ -15,9 +15,17 @@ from . import exceptions
|
|||||||
class Content(object):
|
class Content(object):
|
||||||
|
|
||||||
def get(self, index, n_cols):
|
def get(self, index, n_cols):
|
||||||
|
"""
|
||||||
|
Grab the item at the given index, and format the text to fit a width of
|
||||||
|
n columns.
|
||||||
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def iterate(self, index, step, n_cols=70):
|
def iterate(self, index, step, n_cols=70):
|
||||||
|
"""
|
||||||
|
Return an iterator that starts and the current index and increments
|
||||||
|
by the given step.
|
||||||
|
"""
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
if step < 0 and index < 0:
|
if step < 0 and index < 0:
|
||||||
@@ -30,6 +38,13 @@ class Content(object):
|
|||||||
break
|
break
|
||||||
index += step
|
index += step
|
||||||
|
|
||||||
|
@property
|
||||||
|
def range(self):
|
||||||
|
"""
|
||||||
|
Return the minimm and maximum valid indicies.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def flatten_comments(comments, root_level=0):
|
def flatten_comments(comments, root_level=0):
|
||||||
"""
|
"""
|
||||||
@@ -305,6 +320,10 @@ class SubmissionContent(Content):
|
|||||||
submission = reddit.get_submission(url, comment_sort=order)
|
submission = reddit.get_submission(url, comment_sort=order)
|
||||||
return cls(submission, loader, indent_size, max_indent_level, order)
|
return cls(submission, loader, indent_size, max_indent_level, order)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def range(self):
|
||||||
|
return -1, len(self._comment_data) - 1
|
||||||
|
|
||||||
def get(self, index, n_cols=70):
|
def get(self, index, n_cols=70):
|
||||||
"""
|
"""
|
||||||
Grab the `i`th submission, with the title field formatted to fit inside
|
Grab the `i`th submission, with the title field formatted to fit inside
|
||||||
@@ -559,6 +578,13 @@ class SubredditContent(Content):
|
|||||||
# We made it!
|
# We made it!
|
||||||
return cls(display_name, submissions, loader, order=display_order)
|
return cls(display_name, submissions, loader, order=display_order)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def range(self):
|
||||||
|
# Note that for subreddits, the submissions are generated lazily and
|
||||||
|
# there is no actual "end" index. Instead, we return the bottom index
|
||||||
|
# that we have loaded so far.
|
||||||
|
return 0, len(self._submission_data) - 1
|
||||||
|
|
||||||
def get(self, index, n_cols=70):
|
def get(self, index, n_cols=70):
|
||||||
"""
|
"""
|
||||||
Grab the `i`th submission, with the title field formatted to fit inside
|
Grab the `i`th submission, with the title field formatted to fit inside
|
||||||
@@ -615,6 +641,15 @@ class SubscriptionContent(Content):
|
|||||||
except IndexError:
|
except IndexError:
|
||||||
raise exceptions.SubscriptionError('No content')
|
raise exceptions.SubscriptionError('No content')
|
||||||
|
|
||||||
|
# Load 1024 subscriptions up front (one http request's worth)
|
||||||
|
# For most people this should be all of their subscriptions. Doing thi
|
||||||
|
# allows the user to jump to the end of the page with `G`.
|
||||||
|
if name != 'Popular Subreddits':
|
||||||
|
try:
|
||||||
|
self.get(1023)
|
||||||
|
except IndexError:
|
||||||
|
pass
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_user(cls, reddit, loader, content_type='subreddit'):
|
def from_user(cls, reddit, loader, content_type='subreddit'):
|
||||||
if content_type == 'subreddit':
|
if content_type == 'subreddit':
|
||||||
@@ -632,6 +667,10 @@ class SubscriptionContent(Content):
|
|||||||
|
|
||||||
return cls(name, items, loader)
|
return cls(name, items, loader)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def range(self):
|
||||||
|
return 0, len(self._subscription_data) - 1
|
||||||
|
|
||||||
def get(self, index, n_cols=70):
|
def get(self, index, n_cols=70):
|
||||||
"""
|
"""
|
||||||
Grab the `i`th object, with the title field formatted to fit
|
Grab the `i`th object, with the title field formatted to fit
|
||||||
|
|||||||
@@ -519,11 +519,6 @@ class Controller(object):
|
|||||||
>>> def upvote(self, *args)
|
>>> def upvote(self, *args)
|
||||||
>> ...
|
>> ...
|
||||||
|
|
||||||
Register a default behavior by using `None`.
|
|
||||||
>>> @Controller.register(None)
|
|
||||||
>>> def default_func(self, *args)
|
|
||||||
>>> ...
|
|
||||||
|
|
||||||
Bind the controller to a class instance and trigger a key. Additional
|
Bind the controller to a class instance and trigger a key. Additional
|
||||||
arguments will be passed to the function.
|
arguments will be passed to the function.
|
||||||
>>> controller = Controller(self)
|
>>> controller = Controller(self)
|
||||||
@@ -538,6 +533,8 @@ class Controller(object):
|
|||||||
# Build a list of parent controllers that follow the object's MRO
|
# Build a list of parent controllers that follow the object's MRO
|
||||||
# to check if any parent controllers have registered the keypress
|
# to check if any parent controllers have registered the keypress
|
||||||
self.parents = inspect.getmro(type(self))[:-1]
|
self.parents = inspect.getmro(type(self))[:-1]
|
||||||
|
# Keep track of last key press for doubles like `gg`
|
||||||
|
self.last_char = None
|
||||||
|
|
||||||
if not keymap:
|
if not keymap:
|
||||||
return
|
return
|
||||||
@@ -551,6 +548,18 @@ class Controller(object):
|
|||||||
if isinstance(command, Command):
|
if isinstance(command, Command):
|
||||||
for key in keymap.get(command):
|
for key in keymap.get(command):
|
||||||
val = keymap.parse(key)
|
val = keymap.parse(key)
|
||||||
|
# If a double key press is defined, the first half
|
||||||
|
# must be unbound
|
||||||
|
if isinstance(val, tuple):
|
||||||
|
if controller.character_map.get(val[0]) is not None:
|
||||||
|
raise exceptions.ConfigError(
|
||||||
|
"Invalid configuration! `%s` is bound to "
|
||||||
|
"duplicate commands in the "
|
||||||
|
"%s" % (key, controller.__name__))
|
||||||
|
# Mark the first half of the double with None so
|
||||||
|
# that no other command can use it
|
||||||
|
controller.character_map[val[0]] = None
|
||||||
|
|
||||||
# Check if the key is already programmed to trigger a
|
# Check if the key is already programmed to trigger a
|
||||||
# different function.
|
# different function.
|
||||||
if controller.character_map.get(val, func) != func:
|
if controller.character_map.get(val, func) != func:
|
||||||
@@ -569,16 +578,19 @@ class Controller(object):
|
|||||||
# Check if the controller (or any of the controller's parents) have
|
# Check if the controller (or any of the controller's parents) have
|
||||||
# registered a function to the given key
|
# registered a function to the given key
|
||||||
for controller in self.parents:
|
for controller in self.parents:
|
||||||
|
func = controller.character_map.get((self.last_char, char))
|
||||||
if func:
|
if func:
|
||||||
break
|
break
|
||||||
func = controller.character_map.get(char)
|
func = controller.character_map.get(char)
|
||||||
# If the controller has not registered the key, check if there is a
|
|
||||||
# default function registered
|
|
||||||
for controller in self.parents:
|
|
||||||
if func:
|
if func:
|
||||||
break
|
break
|
||||||
func = controller.character_map.get(None)
|
|
||||||
return func(self.instance, *args, **kwargs) if func else None
|
if func:
|
||||||
|
self.last_char = None
|
||||||
|
return func(self.instance, *args, **kwargs)
|
||||||
|
else:
|
||||||
|
self.last_char = char
|
||||||
|
return None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def register(cls, *chars):
|
def register(cls, *chars):
|
||||||
@@ -645,8 +657,8 @@ class KeyMap(object):
|
|||||||
raise exceptions.ConfigError('Invalid configuration! `%s` key is '
|
raise exceptions.ConfigError('Invalid configuration! `%s` key is '
|
||||||
'undefined' % command.val)
|
'undefined' % command.val)
|
||||||
|
|
||||||
@staticmethod
|
@classmethod
|
||||||
def parse(key):
|
def parse(cls, key):
|
||||||
"""
|
"""
|
||||||
Parse a key represented by a string and return its character code.
|
Parse a key represented by a string and return its character code.
|
||||||
"""
|
"""
|
||||||
@@ -663,6 +675,9 @@ class KeyMap(object):
|
|||||||
elif key.startswith('0x'):
|
elif key.startswith('0x'):
|
||||||
# Ascii hex code
|
# Ascii hex code
|
||||||
return int(key, 16)
|
return int(key, 16)
|
||||||
|
elif len(key) == 2:
|
||||||
|
# Double presses
|
||||||
|
return tuple(cls.parse(k) for k in key)
|
||||||
else:
|
else:
|
||||||
# Ascii character
|
# Ascii character
|
||||||
code = ord(key)
|
code = ord(key)
|
||||||
|
|||||||
16
rtv/page.py
16
rtv/page.py
@@ -124,6 +124,22 @@ class Page(object):
|
|||||||
self._move_page(1)
|
self._move_page(1)
|
||||||
self.clear_input_queue()
|
self.clear_input_queue()
|
||||||
|
|
||||||
|
@PageController.register(Command('PAGE_TOP'))
|
||||||
|
def move_page_top(self):
|
||||||
|
self._remove_cursor()
|
||||||
|
self.nav.page_index = self.content.range[0]
|
||||||
|
self.nav.cursor_index = 0
|
||||||
|
self.nav.inverted = False
|
||||||
|
self._add_cursor()
|
||||||
|
|
||||||
|
@PageController.register(Command('PAGE_BOTTOM'))
|
||||||
|
def move_page_bottom(self):
|
||||||
|
self._remove_cursor()
|
||||||
|
self.nav.page_index = self.content.range[1]
|
||||||
|
self.nav.cursor_index = 0
|
||||||
|
self.nav.inverted = True
|
||||||
|
self._add_cursor()
|
||||||
|
|
||||||
@PageController.register(Command('UPVOTE'))
|
@PageController.register(Command('UPVOTE'))
|
||||||
@logged_in
|
@logged_in
|
||||||
def upvote(self):
|
def upvote(self):
|
||||||
|
|||||||
@@ -101,6 +101,8 @@ MOVE_UP = k, <KEY_UP>
|
|||||||
MOVE_DOWN = j, <KEY_DOWN>
|
MOVE_DOWN = j, <KEY_DOWN>
|
||||||
PAGE_UP = m, <KEY_PPAGE>, <NAK>
|
PAGE_UP = m, <KEY_PPAGE>, <NAK>
|
||||||
PAGE_DOWN = n, <KEY_NPAGE>, <EOT>
|
PAGE_DOWN = n, <KEY_NPAGE>, <EOT>
|
||||||
|
PAGE_TOP = gg
|
||||||
|
PAGE_BOTTOM = G
|
||||||
UPVOTE = a
|
UPVOTE = a
|
||||||
DOWNVOTE = z
|
DOWNVOTE = z
|
||||||
LOGIN = u
|
LOGIN = u
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
171
tests/cassettes/test_submission_move_top_bottom.yaml
Normal file
171
tests/cassettes/test_submission_move_top_bottom.yaml
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
interactions:
|
||||||
|
- request:
|
||||||
|
body: null
|
||||||
|
headers:
|
||||||
|
Accept: ['*/*']
|
||||||
|
Accept-Encoding: ['gzip, deflate']
|
||||||
|
Connection: [keep-alive]
|
||||||
|
User-Agent: [rtv test suite PRAW/3.5.0 Python/3.4.0 b'Linux-3.13.0-92-generic-x86_64-with-Ubuntu-14.04-trusty']
|
||||||
|
method: GET
|
||||||
|
uri: https://www.reddit.com/r/Python/comments/2xmo63.json
|
||||||
|
response:
|
||||||
|
body:
|
||||||
|
string: !!binary |
|
||||||
|
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
|
||||||
|
headers:
|
||||||
|
CF-RAY: [2cd06f2da43a2894-SJC]
|
||||||
|
Connection: [keep-alive]
|
||||||
|
Content-Encoding: [gzip]
|
||||||
|
Content-Length: ['7674']
|
||||||
|
Content-Type: [application/json; charset=UTF-8]
|
||||||
|
Date: ['Thu, 04 Aug 2016 07:53:12 GMT']
|
||||||
|
Server: [cloudflare-nginx]
|
||||||
|
Set-Cookie: ['__cfduid=deaa9dbd54fbd8a077e39b5959dec2bc01470297192; expires=Fri,
|
||||||
|
04-Aug-17 07:53:12 GMT; path=/; domain=.reddit.com; HttpOnly']
|
||||||
|
Strict-Transport-Security: [max-age=15552000; includeSubDomains; preload]
|
||||||
|
Vary: [accept-encoding]
|
||||||
|
X-Moose: [majestic]
|
||||||
|
access-control-allow-origin: ['*']
|
||||||
|
access-control-expose-headers: ['X-Reddit-Tracking, X-Moose']
|
||||||
|
cache-control: ['max-age=0, must-revalidate']
|
||||||
|
x-content-type-options: [nosniff]
|
||||||
|
x-frame-options: [SAMEORIGIN]
|
||||||
|
x-reddit-tracking: ['https://pixel.redditmedia.com/pixel/of_destiny.png?v=3mNLLiHWXXIBcSfLlY62cXrSkjuA13zPmWYuKQQ2GBZ40AE3i97WARhJi%2FzYCgZC7sGW2UGKac4%3D']
|
||||||
|
x-ua-compatible: [IE=edge]
|
||||||
|
x-xss-protection: [1; mode=block]
|
||||||
|
status: {code: 200, message: OK}
|
||||||
|
version: 1
|
||||||
@@ -172,7 +172,7 @@ def test_content_submission(reddit, terminal):
|
|||||||
content = SubmissionContent(submission, terminal.loader)
|
content = SubmissionContent(submission, terminal.loader)
|
||||||
|
|
||||||
# Everything is loaded upon instantiation
|
# Everything is loaded upon instantiation
|
||||||
assert len(content._comment_data) == 45
|
assert content.range == (-1, 44)
|
||||||
assert content.get(-1)['type'] == 'Submission'
|
assert content.get(-1)['type'] == 'Submission'
|
||||||
assert content.get(40)['type'] == 'Comment'
|
assert content.get(40)['type'] == 'Comment'
|
||||||
|
|
||||||
@@ -200,13 +200,13 @@ def test_content_submission(reddit, terminal):
|
|||||||
assert data['count'] == 3
|
assert data['count'] == 3
|
||||||
assert data['hidden'] is True
|
assert data['hidden'] is True
|
||||||
assert data['level'] >= content.get(3)['level']
|
assert data['level'] >= content.get(3)['level']
|
||||||
assert len(content._comment_data) == 43
|
assert content.range == (-1, 42)
|
||||||
|
|
||||||
# Toggling again expands the children
|
# Toggling again expands the children
|
||||||
content.toggle(2)
|
content.toggle(2)
|
||||||
data = content.get(2)
|
data = content.get(2)
|
||||||
assert data['hidden'] is False
|
assert data['hidden'] is False
|
||||||
assert len(content._comment_data) == 45
|
assert content.range == (-1, 44)
|
||||||
|
|
||||||
|
|
||||||
def test_content_submission_load_more_comments(reddit, terminal):
|
def test_content_submission_load_more_comments(reddit, terminal):
|
||||||
@@ -219,7 +219,8 @@ def test_content_submission_load_more_comments(reddit, terminal):
|
|||||||
# More comments load when toggled
|
# More comments load when toggled
|
||||||
assert content.get(390)['type'] == 'MoreComments'
|
assert content.get(390)['type'] == 'MoreComments'
|
||||||
content.toggle(390)
|
content.toggle(390)
|
||||||
assert len(content._comment_data) > 390
|
assert content.range[0] == -1
|
||||||
|
assert content.range[1] > 390
|
||||||
assert content.get(390)['type'] == 'Comment'
|
assert content.get(390)['type'] == 'Comment'
|
||||||
|
|
||||||
|
|
||||||
@@ -254,7 +255,7 @@ def test_content_subreddit_initialize(reddit, terminal):
|
|||||||
content = SubredditContent('python', submissions, terminal.loader, 'top')
|
content = SubredditContent('python', submissions, terminal.loader, 'top')
|
||||||
assert content.name == 'python'
|
assert content.name == 'python'
|
||||||
assert content.order == 'top'
|
assert content.order == 'top'
|
||||||
assert len(content._submission_data) == 1
|
assert content.range == (0, 0)
|
||||||
|
|
||||||
|
|
||||||
def test_content_subreddit_initialize_invalid(reddit, terminal):
|
def test_content_subreddit_initialize_invalid(reddit, terminal):
|
||||||
@@ -271,7 +272,7 @@ def test_content_subreddit(reddit, terminal):
|
|||||||
content = SubredditContent('front', submissions, terminal.loader)
|
content = SubredditContent('front', submissions, terminal.loader)
|
||||||
|
|
||||||
# Submissions are loaded on demand, excluding for the first one
|
# Submissions are loaded on demand, excluding for the first one
|
||||||
assert len(content._submission_data) == 1
|
assert content.range == (0, 0)
|
||||||
assert content.get(0)['type'] == 'Submission'
|
assert content.get(0)['type'] == 'Submission'
|
||||||
|
|
||||||
for data in content.iterate(0, 1):
|
for data in content.iterate(0, 1):
|
||||||
@@ -295,7 +296,7 @@ def test_content_subreddit_load_more(reddit, terminal):
|
|||||||
content = SubredditContent('front', submissions, terminal.loader)
|
content = SubredditContent('front', submissions, terminal.loader)
|
||||||
|
|
||||||
assert content.get(50)['type'] == 'Submission'
|
assert content.get(50)['type'] == 'Submission'
|
||||||
assert len(content._submission_data) == 51
|
assert content.range == (0, 50)
|
||||||
|
|
||||||
for i, data in enumerate(islice(content.iterate(0, 1), 0, 50)):
|
for i, data in enumerate(islice(content.iterate(0, 1), 0, 50)):
|
||||||
assert all(k in data for k in ('object', 'n_rows', 'offset', 'type',
|
assert all(k in data for k in ('object', 'n_rows', 'offset', 'type',
|
||||||
@@ -416,6 +417,7 @@ def test_content_subscription(reddit, terminal):
|
|||||||
# These are static
|
# These are static
|
||||||
assert content.name == 'Popular Subreddits'
|
assert content.name == 'Popular Subreddits'
|
||||||
assert content.order is None
|
assert content.order is None
|
||||||
|
assert content.range == (0, 0)
|
||||||
|
|
||||||
# Validate content
|
# Validate content
|
||||||
for data in islice(content.iterate(0, 1), 20):
|
for data in islice(content.iterate(0, 1), 20):
|
||||||
@@ -425,6 +427,8 @@ def test_content_subscription(reddit, terminal):
|
|||||||
for val in data.values():
|
for val in data.values():
|
||||||
assert not isinstance(val, six.binary_type)
|
assert not isinstance(val, six.binary_type)
|
||||||
|
|
||||||
|
assert content.range == (0, 19)
|
||||||
|
|
||||||
|
|
||||||
def test_content_subreddit_saved(reddit, oauth, refresh_token, terminal):
|
def test_content_subreddit_saved(reddit, oauth, refresh_token, terminal):
|
||||||
|
|
||||||
|
|||||||
@@ -249,6 +249,41 @@ def test_objects_controller():
|
|||||||
assert controller_c.trigger('3') is None
|
assert controller_c.trigger('3') is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_objects_controller_double_press():
|
||||||
|
|
||||||
|
class ControllerA(Controller):
|
||||||
|
character_map = {}
|
||||||
|
|
||||||
|
@ControllerA.register(Command('F1'))
|
||||||
|
def call_page(_):
|
||||||
|
return '1'
|
||||||
|
|
||||||
|
@ControllerA.register(Command('F2'))
|
||||||
|
def call_page(_):
|
||||||
|
return '2'
|
||||||
|
|
||||||
|
keymap = KeyMap({'F1': ['gg'], 'F2': ['a']})
|
||||||
|
controller_a = ControllerA(None, keymap=keymap)
|
||||||
|
|
||||||
|
# Double press
|
||||||
|
controller_a.last_char = None
|
||||||
|
assert controller_a.trigger('g') is None
|
||||||
|
assert controller_a.trigger('g') == '1'
|
||||||
|
assert controller_a.trigger('g') is None
|
||||||
|
|
||||||
|
# Executing another command cancels the chain
|
||||||
|
controller_a.last_char = None
|
||||||
|
assert controller_a.trigger('g') is None
|
||||||
|
assert controller_a.trigger('a') == '2'
|
||||||
|
assert controller_a.trigger('g') is None
|
||||||
|
|
||||||
|
# Pressing an invalid key cancels the chain
|
||||||
|
controller_a.last_char = None
|
||||||
|
assert controller_a.trigger('g') is None
|
||||||
|
assert controller_a.trigger('b') is None
|
||||||
|
assert controller_a.trigger('g') is None
|
||||||
|
|
||||||
|
|
||||||
def test_objects_controller_command():
|
def test_objects_controller_command():
|
||||||
|
|
||||||
class ControllerA(Controller):
|
class ControllerA(Controller):
|
||||||
@@ -278,6 +313,15 @@ def test_objects_controller_command():
|
|||||||
# Reset the character map
|
# Reset the character map
|
||||||
ControllerA.character_map = {Command('REFRESH'): 0, Command('UPVOTE'): 0}
|
ControllerA.character_map = {Command('REFRESH'): 0, Command('UPVOTE'): 0}
|
||||||
|
|
||||||
|
# A double command can't share the first key with a single comand
|
||||||
|
keymap = KeyMap({'REFRESH': ['gg'], 'UPVOTE': ['g']})
|
||||||
|
with pytest.raises(exceptions.ConfigError) as e:
|
||||||
|
ControllerA(None, keymap=keymap)
|
||||||
|
assert 'ControllerA' in six.text_type(e)
|
||||||
|
|
||||||
|
# Reset the character map
|
||||||
|
ControllerA.character_map = {Command('REFRESH'): 0, Command('UPVOTE'): 0}
|
||||||
|
|
||||||
# All commands must be defined in the keymap
|
# All commands must be defined in the keymap
|
||||||
keymap = KeyMap({'REFRESH': [0x10]})
|
keymap = KeyMap({'REFRESH': [0x10]})
|
||||||
with pytest.raises(exceptions.ConfigError) as e:
|
with pytest.raises(exceptions.ConfigError) as e:
|
||||||
@@ -306,12 +350,14 @@ def test_objects_keymap():
|
|||||||
bindings = {
|
bindings = {
|
||||||
'refresh': ['a', 0x12, '<LF>', '<KEY_UP>'],
|
'refresh': ['a', 0x12, '<LF>', '<KEY_UP>'],
|
||||||
'exit': [],
|
'exit': [],
|
||||||
Command('UPVOTE'): ['b', '<KEY_F5>']
|
Command('UPVOTE'): ['b', '<KEY_F5>'],
|
||||||
|
Command('PAGE_TOP'): ['gg']
|
||||||
}
|
}
|
||||||
|
|
||||||
keymap = KeyMap(bindings)
|
keymap = KeyMap(bindings)
|
||||||
assert keymap.get(Command('REFRESH')) == ['a', 0x12, '<LF>', '<KEY_UP>']
|
assert keymap.get(Command('REFRESH')) == ['a', 0x12, '<LF>', '<KEY_UP>']
|
||||||
assert keymap.get(Command('exit')) == []
|
assert keymap.get(Command('exit')) == []
|
||||||
|
assert keymap.get(Command('PAGE_TOP')) == ['gg']
|
||||||
assert keymap.get('upvote') == ['b', '<KEY_F5>']
|
assert keymap.get('upvote') == ['b', '<KEY_F5>']
|
||||||
with pytest.raises(exceptions.ConfigError) as e:
|
with pytest.raises(exceptions.ConfigError) as e:
|
||||||
keymap.get('downvote')
|
keymap.get('downvote')
|
||||||
@@ -331,7 +377,8 @@ def test_objects_keymap():
|
|||||||
assert KeyMap.parse('<LF>') == 10
|
assert KeyMap.parse('<LF>') == 10
|
||||||
assert KeyMap.parse('<KEY_UP>') == 259
|
assert KeyMap.parse('<KEY_UP>') == 259
|
||||||
assert KeyMap.parse('<KEY_F5>') == 269
|
assert KeyMap.parse('<KEY_F5>') == 269
|
||||||
for key in ('', None, '<lf>', '<DNS>', '<KEY_UD>', '♬'):
|
assert KeyMap.parse('gg') == (103, 103)
|
||||||
|
for key in ('', None, '<lf>', '<DNS>', '<KEY_UD>', '♬', 'ggg'):
|
||||||
with pytest.raises(exceptions.ConfigError) as e:
|
with pytest.raises(exceptions.ConfigError) as e:
|
||||||
keymap.parse(key)
|
keymap.parse(key)
|
||||||
assert six.text_type(key) in six.text_type(e)
|
assert six.text_type(key) in six.text_type(e)
|
||||||
|
|||||||
@@ -95,6 +95,16 @@ def test_submission_open(submission_page, terminal):
|
|||||||
assert terminal.open_browser.called
|
assert terminal.open_browser.called
|
||||||
|
|
||||||
|
|
||||||
|
def test_submission_move_top_bottom(submission_page):
|
||||||
|
|
||||||
|
submission_page.controller.trigger('G')
|
||||||
|
assert submission_page.nav.absolute_index == 44
|
||||||
|
|
||||||
|
submission_page.controller.trigger('g')
|
||||||
|
submission_page.controller.trigger('g')
|
||||||
|
assert submission_page.nav.absolute_index == -1
|
||||||
|
|
||||||
|
|
||||||
def test_submission_pager(submission_page, terminal):
|
def test_submission_pager(submission_page, terminal):
|
||||||
|
|
||||||
# View a submission with the pager
|
# View a submission with the pager
|
||||||
|
|||||||
Reference in New Issue
Block a user