summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/commands/global_test.py61
-rw-r--r--tests/helper_test.py78
-rw-r--r--tests/utilities.py10
3 files changed, 141 insertions, 8 deletions
diff --git a/tests/commands/global_test.py b/tests/commands/global_test.py
index 860a6ccb..9489c909 100644
--- a/tests/commands/global_test.py
+++ b/tests/commands/global_test.py
@@ -17,6 +17,7 @@
"""Tests for global commands."""
from __future__ import absolute_import
+import os
from twisted.trial import unittest
from twisted.internet.defer import inlineCallbacks
@@ -116,3 +117,63 @@ class TestComposeCommand(unittest.TestCase):
self.assertFalse(envelope.sign)
self.assertIs(envelope.sign_key, None)
+
+
+class TestExternalCommand(unittest.TestCase):
+
+ def test_no_spawn_no_stdin_success(self):
+ ui = mock.Mock()
+ cmd = g_commands.ExternalCommand(u'true', refocus=False)
+ cmd.apply(ui)
+ ui.notify.assert_not_called()
+
+ def test_no_spawn_stdin_success(self):
+ ui = mock.Mock()
+ cmd = g_commands.ExternalCommand(u"awk '{ exit $0 }'", stdin=u'0',
+ refocus=False)
+ cmd.apply(ui)
+ ui.notify.assert_not_called()
+
+ def test_no_spawn_no_stdin_attached(self):
+ ui = mock.Mock()
+ cmd = g_commands.ExternalCommand(u'test -t 0', refocus=False)
+ cmd.apply(ui)
+ ui.notify.assert_not_called()
+
+ def test_no_spawn_stdin_attached(self):
+ ui = mock.Mock()
+ cmd = g_commands.ExternalCommand(u"test -t 0", stdin=u'0', refocus=False)
+ cmd.apply(ui)
+ ui.notify.assert_called_once_with('', priority='error')
+
+ def test_no_spawn_failure(self):
+ ui = mock.Mock()
+ cmd = g_commands.ExternalCommand(u'false', refocus=False)
+ cmd.apply(ui)
+ ui.notify.assert_called_once_with('', priority='error')
+
+ @mock.patch('alot.commands.globals.settings.get', mock.Mock(return_value=''))
+ @mock.patch.dict(os.environ, {'DISPLAY': ':0'})
+ def test_spawn_no_stdin_success(self):
+ ui = mock.Mock()
+ cmd = g_commands.ExternalCommand(u'true', refocus=False, spawn=True)
+ cmd.apply(ui)
+ ui.notify.assert_not_called()
+
+ @mock.patch('alot.commands.globals.settings.get', mock.Mock(return_value=''))
+ @mock.patch.dict(os.environ, {'DISPLAY': ':0'})
+ def test_spawn_stdin_success(self):
+ ui = mock.Mock()
+ cmd = g_commands.ExternalCommand(
+ u"awk '{ exit $0 }'",
+ stdin=u'0', refocus=False, spawn=True)
+ cmd.apply(ui)
+ ui.notify.assert_not_called()
+
+ @mock.patch('alot.commands.globals.settings.get', mock.Mock(return_value=''))
+ @mock.patch.dict(os.environ, {'DISPLAY': ':0'})
+ def test_spawn_failure(self):
+ ui = mock.Mock()
+ cmd = g_commands.ExternalCommand(u'false', refocus=False, spawn=True)
+ cmd.apply(ui)
+ ui.notify.assert_called_once_with('', priority='error')
diff --git a/tests/helper_test.py b/tests/helper_test.py
index 62e37ed8..c2927725 100644
--- a/tests/helper_test.py
+++ b/tests/helper_test.py
@@ -18,17 +18,21 @@
"""Test suite for alot.helper module."""
from __future__ import absolute_import
-
import datetime
import email
import errno
+import os
import random
-import unittest
import mock
+from twisted.trial import unittest
+from twisted.internet.defer import inlineCallbacks
+from twisted.internet.error import ProcessTerminated
from alot import helper
+from . import utilities
+
# Descriptive names for tests often violate PEP8. That's not an issue, users
# aren't meant to call these functions.
# pylint: disable=invalid-name
@@ -257,7 +261,7 @@ class TestPrettyDatetime(unittest.TestCase):
self.assertEqual(actual, expected)
# Returns 'just now', instead of 'from future' or something similar
- @unittest.expectedFailure
+ @utilities.expected_failure
def test_future_minutes(self):
test = self.now + datetime.timedelta(minutes=5)
actual = helper.pretty_datetime(test)
@@ -265,7 +269,7 @@ class TestPrettyDatetime(unittest.TestCase):
self.assertEqual(actual, expected)
# Returns 'just now', instead of 'from future' or something similar
- @unittest.expectedFailure
+ @utilities.expected_failure
def test_future_hours(self):
test = self.now + datetime.timedelta(hours=1)
actual = helper.pretty_datetime(test)
@@ -273,7 +277,7 @@ class TestPrettyDatetime(unittest.TestCase):
self.assertEqual(actual, expected)
# Returns 'just now', instead of 'from future' or something similar
- @unittest.expectedFailure
+ @utilities.expected_failure
def test_future_days(self):
def make_expected():
# Uses the hourfmt instead of the hourminfmt from pretty_datetime
@@ -290,7 +294,7 @@ class TestPrettyDatetime(unittest.TestCase):
self.assertEqual(actual, expected)
# Returns 'just now', instead of 'from future' or something similar
- @unittest.expectedFailure
+ @utilities.expected_failure
def test_future_week(self):
test = self.now + datetime.timedelta(days=7)
actual = helper.pretty_datetime(test)
@@ -298,7 +302,7 @@ class TestPrettyDatetime(unittest.TestCase):
self.assertEqual(actual, expected)
# Returns 'just now', instead of 'from future' or something similar
- @unittest.expectedFailure
+ @utilities.expected_failure
def test_future_month(self):
test = self.now + datetime.timedelta(days=31)
actual = helper.pretty_datetime(test)
@@ -306,7 +310,7 @@ class TestPrettyDatetime(unittest.TestCase):
self.assertEqual(actual, expected)
# Returns 'just now', instead of 'from future' or something similar
- @unittest.expectedFailure
+ @utilities.expected_failure
def test_future_year(self):
test = self.now + datetime.timedelta(days=365)
actual = helper.pretty_datetime(test)
@@ -402,3 +406,61 @@ class TestEmailAsString(unittest.TestCase):
actual = helper.email_as_string(message)
expected = 'X-Unicode-Header: dummy value\r\n\r\n'
self.assertEqual(actual, expected)
+
+
+class TestShorten(unittest.TestCase):
+
+ def test_lt_maxlen(self):
+ expected = u'a string'
+ actual = helper.shorten(expected, 25)
+ self.assertEqual(expected, actual)
+
+ def test_eq_maxlen(self):
+ expected = 'a string'
+ actual = helper.shorten(expected, len(expected))
+ self.assertEqual(expected, actual)
+
+ def test_gt_maxlen(self):
+ expected = u'a long string…'
+ actual = helper.shorten('a long string that is full of text', 14)
+ self.assertEqual(expected, actual)
+
+
+class TestCallCmdAsync(unittest.TestCase):
+
+ @inlineCallbacks
+ def test_no_stdin(self):
+ ret = yield helper.call_cmd_async(['echo', '-n', 'foo'])
+ self.assertEqual(ret, 'foo')
+
+ @inlineCallbacks
+ def test_stdin(self):
+ ret = yield helper.call_cmd_async(['cat', '-'], stdin='foo')
+ self.assertEqual(ret, 'foo')
+
+ @inlineCallbacks
+ def test_env_set(self):
+ with mock.patch.dict(os.environ, {}, clear=True):
+ ret = yield helper.call_cmd_async(
+ # Thanks to the future import it doesn't matter if python is
+ # python2 or python3
+ ['python', '-c', 'from __future__ import print_function; '
+ 'import os; '
+ 'print(os.environ.get("foo", "fail"), end="")'
+ ],
+ env={'foo': 'bar'})
+ self.assertEqual(ret, 'bar')
+
+ @inlineCallbacks
+ def test_env_doesnt_pollute(self):
+ with mock.patch.dict(os.environ, {}, clear=True):
+ yield helper.call_cmd_async(['echo', '-n', 'foo'],
+ env={'foo': 'bar'})
+ self.assertEqual(os.environ, {})
+
+ @inlineCallbacks
+ def test_command_fails(self):
+ with self.assertRaises(ProcessTerminated) as cm:
+ yield helper.call_cmd_async(['_____better_not_exist'])
+ self.assertEqual(cm.exception.exitCode, 1)
+ self.assertTrue(cm.exception.stderr)
diff --git a/tests/utilities.py b/tests/utilities.py
index 402feb38..8123afd8 100644
--- a/tests/utilities.py
+++ b/tests/utilities.py
@@ -171,3 +171,13 @@ def make_key(revoked=False, expired=False, invalid=False, can_encrypt=True,
mock_key.can_sign = can_sign
return mock_key
+
+
+def expected_failure(func):
+ """For marking expected failures for twisted.trial based unit tests.
+
+ The builtin unittest.expectedFailure does not work with twisted.trail,
+ there is an outstanding bug for this, but no one has ever fixed it.
+ """
+ func.todo = 'expected failure'
+ return func