Full coverage and lint for display.ops

This commit is contained in:
Jakub Warmuz 2015-05-03 22:15:30 +00:00
parent 138a9e9f01
commit b4f99df798
No known key found for this signature in database
GPG key ID: 2A7BAD3A489B52EA
2 changed files with 149 additions and 11 deletions

View file

@ -15,30 +15,49 @@ util = zope.component.getUtility # pylint: disable=invalid-name
def choose_plugin(prepared, question):
"""Allow the user to choose ther plugin.
:param list prepared:
:param list prepared: List of `~.PluginEntryPoint`.
:param str question: Question to be presented to the user.
:returns: Plugin entry point chosen by the user.
:rtype: `~.PluginEntryPoint`
"""
opts = [plugin_ep.name_with_description
+ (" [Misconfigured]" if plugin_ep.misconfigured else "")
for plugin_ep in prepared.itervalues()]
for plugin_ep in prepared]
while True:
code, index = util(interfaces.IDisplay).menu(
question, opts, help_label="More Info")
if code == display_util.OK:
return prepared[index][0]
return prepared[index]
elif code == display_util.HELP:
if prepared[index][1] is not None:
if prepared[index].misconfigured:
msg = "Reported Error: %s" % prepared[index].prepare()
else:
msg = prepared[index][0].init().more_info()
msg = prepared[index].init().more_info()
util(interfaces.IDisplay).notification(
msg, height=display_util.HEIGHT)
else:
return None
def _pick_plugin(config, default, plugins, question, ifaces):
def pick_plugin(config, default, plugins, question, ifaces):
"""Pick plugin.
:param letsencrypt.client.interfaces.IConfig: Configuration
:param str default: Plugin name supplied by user or ``None``.
:param letsencrypt.client.plugins.disco.PluginsRegistry plugins:
All plugins registered as entry points.
:param str question: Question to be presented to the user in case
multiple candidates are found.
:param list ifaces: Interfaces that plugins must provide.
:returns: Initialized plugin.
:rtype: IPlugin
"""
if default is not None:
# throw more UX-friendly error if default not in plugins
filtered = plugins.filter(lambda p_ep: p_ep.name == default)
@ -47,8 +66,8 @@ def _pick_plugin(config, default, plugins, question, ifaces):
filtered.init(config)
verified = filtered.verify(ifaces)
filtered.prepare()
prepared = filtered.available()
verified.prepare()
prepared = verified.available()
if len(prepared) > 1:
logging.debug("Multiple candidate plugins: %s", prepared)
@ -66,14 +85,14 @@ def pick_authenticator(
config, default, plugins, question="How would you "
"like to authenticate with Let's Encrypt CA?"):
"""Pick authentication plugin."""
return _pick_plugin(
return pick_plugin(
config, default, plugins, question, (interfaces.IAuthenticator,))
def pick_installer(config, default, plugins,
question="How would you like to install certificates?"):
"""Pick installer plugin."""
return _pick_plugin(
return pick_plugin(
config, default, plugins, question, (interfaces.IInstaller,))
@ -82,7 +101,7 @@ def pick_configurator(
question="How would you like to authenticate and install "
"certificates?"):
"""Pick configurator plugin."""
return _pick_plugin(
return pick_plugin(
config, default, plugins, question,
(interfaces.IAuthenticator, interfaces.IInstaller))

View file

@ -8,10 +8,129 @@ import mock
import zope.component
from letsencrypt.client import account
from letsencrypt.client import interfaces
from letsencrypt.client import le_util
from letsencrypt.client.display import util as display_util
class ChoosePluginTest(unittest.TestCase):
"""Tests for letsencrypt.client.display.ops.choose_plugin."""
def setUp(self):
zope.component.provideUtility(display_util.FileDisplay(sys.stdout))
self.mock_apache = mock.Mock(
name_with_description="a", misconfigured=True)
self.mock_stand = mock.Mock(
name_with_description="s", misconfigured=False)
self.mock_stand.init().more_info.return_value = "standalone"
self.plugins = [
self.mock_apache,
self.mock_stand,
]
def _call(self):
from letsencrypt.client.display.ops import choose_plugin
return choose_plugin(self.plugins, "Question?")
@mock.patch("letsencrypt.client.display.ops.util")
def test_successful_choice(self, mock_util):
mock_util().menu.return_value = (display_util.OK, 0)
self.assertEqual(self.mock_apache, self._call())
@mock.patch("letsencrypt.client.display.ops.util")
def test_more_info(self, mock_util):
mock_util().menu.side_effect = [
(display_util.HELP, 0),
(display_util.HELP, 1),
(display_util.OK, 1),
]
self.assertEqual(self.mock_stand, self._call())
self.assertEqual(mock_util().notification.call_count, 2)
@mock.patch("letsencrypt.client.display.ops.util")
def test_no_choice(self, mock_util):
mock_util().menu.return_value = (display_util.CANCEL, 0)
self.assertTrue(self._call() is None)
class PickPluginTest(unittest.TestCase):
"""Tests for letsencrypt.client.display.ops.pick_plugin."""
def setUp(self):
self.config = mock.Mock()
self.default = None
self.reg = mock.MagicMock()
self.question = "Question?"
self.ifaces = []
def _call(self):
from letsencrypt.client.display.ops import pick_plugin
return pick_plugin(self.config, self.default, self.reg,
self.question, self.ifaces)
def test_default_provided(self):
self.default = "foo"
self._call()
self.reg.filter.assert_called_once()
def test_no_default(self):
self._call()
self.reg.filter.assert_called_once()
def test_no_candidate(self):
self.assertTrue(self._call() is None)
def test_single(self):
plugin_ep = mock.MagicMock()
plugin_ep.init.return_value = "foo"
self.reg.ifaces().verify().available.return_value = {"bar": plugin_ep}
self.assertEqual("foo", self._call())
def test_multiple(self):
plugin_ep = mock.MagicMock()
plugin_ep.init.return_value = "foo"
self.reg.ifaces().verify().available.return_value = {
"bar": plugin_ep,
"baz": plugin_ep,
}
with mock.patch("letsencrypt.client.display"
".ops.choose_plugin") as mock_choose:
mock_choose.return_value = plugin_ep
self.assertEqual("foo", self._call())
mock_choose.assert_called_once_with(
[plugin_ep, plugin_ep], self.question)
class ConveniencePickPluginTest(unittest.TestCase):
"""Tests for letsencrypt.client.display.ops.pick_*."""
def _test(self, fun, ifaces):
config = mock.Mock()
default = mock.Mock()
plugins = mock.Mock()
with mock.patch("letsencrypt.client.display.ops.pick_plugin") as mock_p:
mock_p.return_value = "foo"
self.assertEqual("foo", fun(config, default, plugins, "Question?"))
mock_p.assert_called_once_with(
config, default, plugins, "Question?", ifaces)
def test_authenticator(self):
from letsencrypt.client.display.ops import pick_authenticator
self._test(pick_authenticator, (interfaces.IAuthenticator,))
def test_installer(self):
from letsencrypt.client.display.ops import pick_installer
self._test(pick_installer, (interfaces.IInstaller,))
def test_configurator(self):
from letsencrypt.client.display.ops import pick_configurator
self._test(pick_configurator, (
interfaces.IAuthenticator, interfaces.IInstaller))
class ChooseAccountTest(unittest.TestCase):
"""Test choose_account."""
def setUp(self):