diff --git a/evennia/utils/evform.py b/evennia/utils/evform.py
index b601c8bfc5..55fa0ec9e2 100644
--- a/evennia/utils/evform.py
+++ b/evennia/utils/evform.py
@@ -429,7 +429,7 @@ class EvForm(object):
def _test():
"test evform. This is used by the unittest system."
- form = EvForm("evennia.utils.evform_test")
+ form = EvForm("evennia.utils.tests.data.evform_example")
# add data to each tagged form cell
form.map(cells={"AA": "|gTom the Bouncer",
diff --git a/evennia/utils/test_resources.py b/evennia/utils/test_resources.py
index f6785a2f1f..b4124b7219 100644
--- a/evennia/utils/test_resources.py
+++ b/evennia/utils/test_resources.py
@@ -35,7 +35,7 @@ class EvenniaTest(TestCase):
self.room1.db.desc = "room_desc"
settings.DEFAULT_HOME = "#%i" % self.room1.id # we must have a default home
# Set up fake prototype module for allowing tests to use named prototypes.
- settings.PROTOTYPE_MODULES = "evennia.utils.test_prototypes"
+ settings.PROTOTYPE_MODULES = "evennia.utils.tests.data.prototypes_example"
self.room2 = create.create_object(self.room_typeclass, key="Room2")
self.exit = create.create_object(self.exit_typeclass, key='out', location=self.room1, destination=self.room2)
self.obj1 = create.create_object(self.object_typeclass, key="Obj", location=self.room1, home=self.room1)
diff --git a/evennia/utils/tests.py b/evennia/utils/tests.py
deleted file mode 100644
index 78ceb45a78..0000000000
--- a/evennia/utils/tests.py
+++ /dev/null
@@ -1,532 +0,0 @@
-from builtins import range
-
-import re
-
-try:
- from django.utils.unittest import TestCase
-except ImportError:
- from django.test import TestCase
-
-from .ansi import ANSIString
-from evennia import utils
-
-from django.conf import settings
-
-
-class ANSIStringTestCase(TestCase):
- def checker(self, ansi, raw, clean):
- """
- Verifies the raw and clean strings of an ANSIString match expected
- output.
- """
- self.assertEqual(unicode(ansi.clean()), clean)
- self.assertEqual(unicode(ansi.raw()), raw)
-
- def table_check(self, ansi, char, code):
- """
- Verifies the indexes in an ANSIString match what they should.
- """
- self.assertEqual(ansi._char_indexes, char)
- self.assertEqual(ansi._code_indexes, code)
-
- def test_instance(self):
- """
- Make sure the ANSIString is always constructed correctly.
- """
- clean = u'This isA|r testTest'
- encoded = u'\x1b[1m\x1b[32mThis is\x1b[1m\x1b[31mA|r test\x1b[0mTest\x1b[0m'
- target = ANSIString(r'|gThis is|rA||r test|nTest|n')
- char_table = [9, 10, 11, 12, 13, 14, 15, 25, 26, 27, 28, 29, 30, 31, 32, 37, 38, 39, 40]
- code_table = [0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 17, 18, 19, 20, 21, 22, 23, 24, 33, 34, 35, 36, 41, 42, 43, 44]
- self.checker(target, encoded, clean)
- self.table_check(target, char_table, code_table)
- self.checker(ANSIString(target), encoded, clean)
- self.table_check(ANSIString(target), char_table, code_table)
- self.checker(ANSIString(encoded, decoded=True), encoded, clean)
- self.table_check(ANSIString(encoded, decoded=True), char_table,
- code_table)
- self.checker(ANSIString('Test'), u'Test', u'Test')
- self.table_check(ANSIString('Test'), [0, 1, 2, 3], [])
- self.checker(ANSIString(''), u'', u'')
-
- def test_slice(self):
- """
- Verifies that slicing an ANSIString results in expected color code
- distribution.
- """
- target = ANSIString(r'|gTest|rTest|n')
- result = target[:3]
- self.checker(result, u'\x1b[1m\x1b[32mTes', u'Tes')
- result = target[:4]
- self.checker(result, u'\x1b[1m\x1b[32mTest\x1b[1m\x1b[31m', u'Test')
- result = target[:]
- self.checker(
- result,
- u'\x1b[1m\x1b[32mTest\x1b[1m\x1b[31mTest\x1b[0m',
- u'TestTest')
- result = target[:-1]
- self.checker(
- result,
- u'\x1b[1m\x1b[32mTest\x1b[1m\x1b[31mTes',
- u'TestTes')
- result = target[0:0]
- self.checker(
- result,
- u'',
- u'')
-
- def test_split(self):
- """
- Verifies that re.split and .split behave similarly and that color
- codes end up where they should.
- """
- target = ANSIString("|gThis is |nA split string|g")
- first = (u'\x1b[1m\x1b[32mThis is \x1b[0m', u'This is ')
- second = (u'\x1b[1m\x1b[32m\x1b[0m split string\x1b[1m\x1b[32m',
- u' split string')
- re_split = re.split('A', target)
- normal_split = target.split('A')
- self.assertEqual(re_split, normal_split)
- self.assertEqual(len(normal_split), 2)
- self.checker(normal_split[0], *first)
- self.checker(normal_split[1], *second)
-
- def test_join(self):
- """
- Verify that joining a set of ANSIStrings works.
- """
- # This isn't the desired behavior, but the expected one. Python
- # concatenates the in-memory representation with the built-in string's
- # join.
- l = [ANSIString("|gTest|r") for _ in range(0, 3)]
- # Force the generator to be evaluated.
- result = "".join(l)
- self.assertEqual(unicode(result), u'TestTestTest')
- result = ANSIString("").join(l)
- self.checker(result, u'\x1b[1m\x1b[32mTest\x1b[1m\x1b[31m\x1b[1m\x1b'
- u'[32mTest\x1b[1m\x1b[31m\x1b[1m\x1b[32mTest'
- u'\x1b[1m\x1b[31m', u'TestTestTest')
-
- def test_len(self):
- """
- Make sure that length reporting on ANSIStrings does not include
- ANSI codes.
- """
- self.assertEqual(len(ANSIString('|gTest|n')), 4)
-
- def test_capitalize(self):
- """
- Make sure that capitalization works. This is the simplest of the
- _transform functions.
- """
- target = ANSIString('|gtest|n')
- result = u'\x1b[1m\x1b[32mTest\x1b[0m'
- self.checker(target.capitalize(), result, u'Test')
-
- def test_mxp_agnostic(self):
- """
- Make sure MXP tags are not treated like ANSI codes, but normal text.
- """
- mxp1 = "|lclook|ltat|le"
- mxp2 = "Start to |lclook here|ltclick somewhere here|le first"
- self.assertEqual(15, len(ANSIString(mxp1)))
- self.assertEqual(53, len(ANSIString(mxp2)))
- # These would indicate an issue with the tables.
- self.assertEqual(len(ANSIString(mxp1)), len(ANSIString(mxp1).split("\n")[0]))
- self.assertEqual(len(ANSIString(mxp2)), len(ANSIString(mxp2).split("\n")[0]))
- self.assertEqual(mxp1, ANSIString(mxp1))
- self.assertEqual(mxp2, unicode(ANSIString(mxp2)))
-
- def test_add(self):
- """
- Verify concatenation works correctly.
- """
- a = ANSIString("|gTest")
- b = ANSIString("|cString|n")
- c = a + b
- result = u'\x1b[1m\x1b[32mTest\x1b[1m\x1b[36mString\x1b[0m'
- self.checker(c, result, u'TestString')
- char_table = [9, 10, 11, 12, 22, 23, 24, 25, 26, 27]
- code_table = [0, 1, 2, 3, 4, 5, 6, 7, 8, 13, 14, 15, 16, 17, 18, 19, 20, 21, 28, 29, 30, 31]
- self.table_check(c, char_table, code_table)
-
- def test_strip(self):
- """
- Test the ansi-aware .strip() methods
- """
- a = ANSIString(" |r Test of stuff |b with spaces |n ")
- b = ANSIString("|r|b")
- self.assertEqual(a.strip(), ANSIString("|rTest of stuff |b with spaces|n"))
- self.assertEqual(a.lstrip(), ANSIString("|rTest of stuff |b with spaces |n "))
- self.assertEqual(a.rstrip(), ANSIString(" |r Test of stuff |b with spaces|n"))
- self.assertEqual(b.strip(), b)
-
-
-class TestIsIter(TestCase):
- def test_is_iter(self):
- self.assertEqual(True, utils.is_iter([1, 2, 3, 4]))
- self.assertEqual(False, utils.is_iter("This is not an iterable"))
-
-
-class TestCrop(TestCase):
- def test_crop(self):
- # No text, return no text
- self.assertEqual("", utils.crop("", width=10, suffix="[...]"))
- # Input length equal to max width, no crop
- self.assertEqual("0123456789", utils.crop("0123456789", width=10, suffix="[...]"))
- # Input length greater than max width, crop (suffix included in width)
- self.assertEqual("0123[...]", utils.crop("0123456789", width=9, suffix="[...]"))
- # Input length less than desired width, no crop
- self.assertEqual("0123", utils.crop("0123", width=9, suffix="[...]"))
- # Width too small or equal to width of suffix
- self.assertEqual("012", utils.crop("0123", width=3, suffix="[...]"))
- self.assertEqual("01234", utils.crop("0123456", width=5, suffix="[...]"))
-
-
-class TestDedent(TestCase):
- def test_dedent(self):
- # Empty string, return empty string
- self.assertEqual("", utils.dedent(""))
- # No leading whitespace
- self.assertEqual("TestDedent", utils.dedent("TestDedent"))
- # Leading whitespace, single line
- self.assertEqual("TestDedent", utils.dedent(" TestDedent"))
- # Leading whitespace, multi line
- input_string = " hello\n world"
- expected_string = "hello\nworld"
- self.assertEqual(expected_string, utils.dedent(input_string))
-
-
-class TestListToString(TestCase):
- """
- Default function header from utils.py:
- list_to_string(inlist, endsep="and", addquote=False)
-
- Examples:
- no endsep:
- [1,2,3] -> '1, 2, 3'
- with endsep=='and':
- [1,2,3] -> '1, 2 and 3'
- with addquote and endsep
- [1,2,3] -> '"1", "2" and "3"'
- """
-
- def test_list_to_string(self):
- self.assertEqual('1, 2, 3', utils.list_to_string([1, 2, 3], endsep=""))
- self.assertEqual('"1", "2", "3"', utils.list_to_string([1, 2, 3], endsep="", addquote=True))
- self.assertEqual('1, 2 and 3', utils.list_to_string([1, 2, 3]))
- self.assertEqual('"1", "2" and "3"', utils.list_to_string([1, 2, 3], endsep="and", addquote=True))
-
-
-class TestMLen(TestCase):
- """
- Verifies that m_len behaves like len in all situations except those
- where MXP may be involved.
- """
-
- def test_non_mxp_string(self):
- self.assertEqual(utils.m_len('Test_string'), 11)
-
- def test_mxp_string(self):
- self.assertEqual(utils.m_len('|lclook|ltat|le'), 2)
-
- def test_mxp_ansi_string(self):
- self.assertEqual(utils.m_len(ANSIString('|lcl|gook|ltat|le|n')), 2)
-
- def test_non_mxp_ansi_string(self):
- self.assertEqual(utils.m_len(ANSIString('|gHello|n')), 5)
-
- def test_list(self):
- self.assertEqual(utils.m_len([None, None]), 2)
-
- def test_dict(self):
- self.assertEqual(utils.m_len({'hello': True, 'Goodbye': False}), 2)
-
-
-from .text2html import TextToHTMLparser
-
-
-class TestTextToHTMLparser(TestCase):
- def setUp(self):
- self.parser = TextToHTMLparser()
-
- def tearDown(self):
- del self.parser
-
- def test_url_scheme_ftp(self):
- self.assertEqual(self.parser.convert_urls('ftp.example.com'),
- 'ftp.example.com')
-
- def test_url_scheme_www(self):
- self.assertEqual(self.parser.convert_urls('www.example.com'),
- 'www.example.com')
-
- def test_url_scheme_ftpproto(self):
- self.assertEqual(self.parser.convert_urls('ftp://ftp.example.com'),
- 'ftp://ftp.example.com')
-
- def test_url_scheme_http(self):
- self.assertEqual(self.parser.convert_urls('http://example.com'),
- 'http://example.com')
-
- def test_url_scheme_https(self):
- self.assertEqual(self.parser.convert_urls('https://example.com'),
- 'https://example.com')
-
- def test_url_chars_slash(self):
- self.assertEqual(self.parser.convert_urls('www.example.com/homedir'),
- 'www.example.com/homedir')
-
- def test_url_chars_colon(self):
- self.assertEqual(self.parser.convert_urls('https://example.com:8000/login/'),
- ''
- 'https://example.com:8000/login/')
-
- def test_url_chars_querystring(self):
- self.assertEqual(self.parser.convert_urls('https://example.com/submitform?field1=val1+val3&field2=val2'),
- ''
- 'https://example.com/submitform?field1=val1+val3&field2=val2')
-
- def test_url_chars_anchor(self):
- self.assertEqual(self.parser.convert_urls('http://www.example.com/menu#section_1'),
- ''
- 'http://www.example.com/menu#section_1')
-
- def test_url_chars_exclam(self):
- self.assertEqual(self.parser.convert_urls('https://groups.google.com/forum/'
- '?fromgroups#!categories/evennia/ainneve'),
- 'https://groups.google.com/forum/?fromgroups#!categories/evennia/ainneve')
-
- def test_url_edge_leadingw(self):
- self.assertEqual(self.parser.convert_urls('wwww.example.com'),
- 'wwww.example.com')
-
- def test_url_edge_following_period_eol(self):
- self.assertEqual(self.parser.convert_urls('www.example.com.'),
- 'www.example.com.')
-
- def test_url_edge_following_period(self):
- self.assertEqual(self.parser.convert_urls('see www.example.com. '),
- 'see www.example.com. ')
-
- def test_url_edge_brackets(self):
- self.assertEqual(self.parser.convert_urls('[http://example.com/]'),
- '[http://example.com/]')
-
- def test_url_edge_multiline(self):
- self.assertEqual(self.parser.convert_urls(' * http://example.com/info\n * bullet'),
- ' * '
- 'http://example.com/info\n * bullet')
-
- def test_url_edge_following_htmlentity(self):
- self.assertEqual(self.parser.convert_urls('http://example.com/info<span>'),
- 'http://example.com/info<span>')
-
- def test_url_edge_surrounded_spans(self):
- self.assertEqual(self.parser.convert_urls('http://example.com/'),
- ''
- 'http://example.com/')
-
-
-from evennia.utils import evmenu
-from mock import Mock
-
-
-class TestEvMenu(TestCase):
- "Run the EvMenu test."
-
- def setUp(self):
- self.caller = Mock()
- self.caller.msg = Mock()
- self.menu = evmenu.EvMenu(self.caller, "evennia.utils.evmenu", startnode="test_start_node",
- persistent=True, cmdset_mergetype="Replace", testval="val", testval2="val2")
-
- def test_kwargsave(self):
- self.assertTrue(hasattr(self.menu, "testval"))
- self.assertTrue(hasattr(self.menu, "testval2"))
-
-
-from evennia.utils import inlinefuncs
-
-
-class TestInlineFuncs(TestCase):
- """Test the nested inlinefunc module"""
-
- def test_nofunc(self):
- self.assertEqual(inlinefuncs.parse_inlinefunc(
- "as$382ewrw w we w werw,|44943}"),
- "as$382ewrw w we w werw,|44943}")
-
- def test_incomplete(self):
- self.assertEqual(inlinefuncs.parse_inlinefunc(
- "testing $blah{without an ending."),
- "testing $blah{without an ending.")
-
- def test_single_func(self):
- self.assertEqual(inlinefuncs.parse_inlinefunc(
- "this is a test with $pad(centered, 20) text in it."),
- "this is a test with centered text in it.")
-
- def test_nested(self):
- self.assertEqual(inlinefuncs.parse_inlinefunc(
- "this $crop(is a test with $pad(padded, 20) text in $pad(pad2, 10) a crop, 80)"),
- "this is a test with padded text in pad2 a crop")
-
- def test_escaped(self):
- self.assertEqual(inlinefuncs.parse_inlinefunc(
- "this should be $pad('''escaped,''' and '''instead,''' cropped $crop(with a long,5) text., 80)"),
- "this should be escaped, and instead, cropped with text. ")
-
- def test_escaped2(self):
- self.assertEqual(inlinefuncs.parse_inlinefunc(
- 'this should be $pad("""escaped,""" and """instead,""" cropped $crop(with a long,5) text., 80)'),
- "this should be escaped, and instead, cropped with text. ")
-
-
-from evennia.utils import evform
-
-
-class TestEvForm(TestCase):
- def test_form(self):
- self.maxDiff = None
- self.assertEqual(evform._test(),
- u'.------------------------------------------------.\n'
- u'| |\n'
- u'| Name: \x1b[0m\x1b[1m\x1b[32mTom\x1b[1m\x1b[32m \x1b'
- u'[1m\x1b[32mthe\x1b[1m\x1b[32m \x1b[0m \x1b[0m '
- u'Account: \x1b[0m\x1b[1m\x1b[33mGriatch '
- u'\x1b[0m\x1b[0m\x1b[1m\x1b[32m\x1b[1m\x1b[32m\x1b[1m\x1b[32m\x1b[1m\x1b[32m\x1b[0m\x1b[0m '
- u'|\n'
- u'| \x1b[0m\x1b[1m\x1b[32mBouncer\x1b[0m \x1b[0m |\n'
- u'| |\n'
- u' >----------------------------------------------<\n'
- u'| |\n'
- u'| Desc: \x1b[0mA sturdy \x1b[0m \x1b[0m'
- u' STR: \x1b[0m12 \x1b[0m\x1b[0m\x1b[0m\x1b[0m'
- u' DEX: \x1b[0m10 \x1b[0m\x1b[0m\x1b[0m\x1b[0m |\n'
- u'| \x1b[0mfellow\x1b[0m \x1b[0m'
- u' INT: \x1b[0m5 \x1b[0m\x1b[0m\x1b[0m\x1b[0m'
- u' STA: \x1b[0m18 \x1b[0m\x1b[0m\x1b[0m\x1b[0m |\n'
- u'| \x1b[0m \x1b[0m'
- u' LUC: \x1b[0m10 \x1b[0m\x1b[0m\x1b[0m'
- u' MAG: \x1b[0m3 \x1b[0m\x1b[0m\x1b[0m |\n'
- u'| |\n'
- u' >----------.-----------------------------------<\n'
- u'| | |\n'
- u'| \x1b[0mHP\x1b[0m|\x1b[0mMV \x1b[0m|\x1b[0mMP\x1b[0m '
- u'| \x1b[0mSkill \x1b[0m|\x1b[0mValue \x1b[0m'
- u'|\x1b[0mExp \x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m |\n'
- u'| ~~+~~~+~~ | ~~~~~~~~~~~+~~~~~~~~~~+~~~~~~~~~~~ |\n'
- u'| \x1b[0m**\x1b[0m|\x1b[0m***\x1b[0m\x1b[0m|\x1b[0m**\x1b[0m\x1b[0m '
- u'| \x1b[0mShooting \x1b[0m|\x1b[0m12 \x1b[0m'
- u'|\x1b[0m550/1200 \x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m |\n'
- u'| \x1b[0m \x1b[0m|\x1b[0m**\x1b[0m \x1b[0m|\x1b[0m*\x1b[0m \x1b[0m '
- u'| \x1b[0mHerbalism \x1b[0m|\x1b[0m14 \x1b[0m'
- u'|\x1b[0m990/1400 \x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m |\n'
- u'| \x1b[0m \x1b[0m|\x1b[0m \x1b[0m|\x1b[0m \x1b[0m '
- u'| \x1b[0mSmithing \x1b[0m|\x1b[0m9 \x1b[0m'
- u'|\x1b[0m205/900 \x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m |\n'
- u'| | |\n'
- u' -----------`-------------------------------------\n')
-
- def test_ansi_escape(self):
- # note that in a msg() call, the result would be the correct |-----,
- # in a print, ansi only gets called once, so ||----- is the result
- self.assertEqual(unicode(evform.EvForm(form={"FORM": "\n||-----"})), "||-----")
-
-
-class TestTimeformat(TestCase):
- """
- Default function header from utils.py:
- time_format(seconds, style=0)
-
- """
-
- def test_style_0(self):
- """Test the style 0 of time_format."""
- self.assertEqual(utils.time_format(0, 0), "00:00")
- self.assertEqual(utils.time_format(28, 0), "00:00")
- self.assertEqual(utils.time_format(92, 0), "00:01")
- self.assertEqual(utils.time_format(300, 0), "00:05")
- self.assertEqual(utils.time_format(660, 0), "00:11")
- self.assertEqual(utils.time_format(3600, 0), "01:00")
- self.assertEqual(utils.time_format(3725, 0), "01:02")
- self.assertEqual(utils.time_format(86350, 0), "23:59")
- self.assertEqual(utils.time_format(86800, 0), "1d 00:06")
- self.assertEqual(utils.time_format(130800, 0), "1d 12:20")
- self.assertEqual(utils.time_format(530800, 0), "6d 03:26")
-
- def test_style_1(self):
- """Test the style 1 of time_format."""
- self.assertEqual(utils.time_format(0, 1), "0s")
- self.assertEqual(utils.time_format(28, 1), "28s")
- self.assertEqual(utils.time_format(92, 1), "1m")
- self.assertEqual(utils.time_format(300, 1), "5m")
- self.assertEqual(utils.time_format(660, 1), "11m")
- self.assertEqual(utils.time_format(3600, 1), "1h")
- self.assertEqual(utils.time_format(3725, 1), "1h")
- self.assertEqual(utils.time_format(86350, 1), "23h")
- self.assertEqual(utils.time_format(86800, 1), "1d")
- self.assertEqual(utils.time_format(130800, 1), "1d")
- self.assertEqual(utils.time_format(530800, 1), "6d")
-
- def test_style_2(self):
- """Test the style 2 of time_format."""
- self.assertEqual(utils.time_format(0, 2), "0 minutes")
- self.assertEqual(utils.time_format(28, 2), "0 minutes")
- self.assertEqual(utils.time_format(92, 2), "1 minute")
- self.assertEqual(utils.time_format(300, 2), "5 minutes")
- self.assertEqual(utils.time_format(660, 2), "11 minutes")
- self.assertEqual(utils.time_format(3600, 2), "1 hour, 0 minutes")
- self.assertEqual(utils.time_format(3725, 2), "1 hour, 2 minutes")
- self.assertEqual(utils.time_format(86350, 2), "23 hours, 59 minutes")
- self.assertEqual(utils.time_format(86800, 2),
- "1 day, 0 hours, 6 minutes")
- self.assertEqual(utils.time_format(130800, 2),
- "1 day, 12 hours, 20 minutes")
- self.assertEqual(utils.time_format(530800, 2),
- "6 days, 3 hours, 26 minutes")
-
- def test_style_3(self):
- """Test the style 3 of time_format."""
- self.assertEqual(utils.time_format(0, 3), "")
- self.assertEqual(utils.time_format(28, 3), "28 seconds")
- self.assertEqual(utils.time_format(92, 3), "1 minute 32 seconds")
- self.assertEqual(utils.time_format(300, 3), "5 minutes 0 seconds")
- self.assertEqual(utils.time_format(660, 3), "11 minutes 0 seconds")
- self.assertEqual(utils.time_format(3600, 3),
- "1 hour, 0 minutes")
- self.assertEqual(utils.time_format(3725, 3),
- "1 hour, 2 minutes 5 seconds")
- self.assertEqual(utils.time_format(86350, 3),
- "23 hours, 59 minutes 10 seconds")
- self.assertEqual(utils.time_format(86800, 3),
- "1 day, 0 hours, 6 minutes 40 seconds")
- self.assertEqual(utils.time_format(130800, 3),
- "1 day, 12 hours, 20 minutes 0 seconds")
- self.assertEqual(utils.time_format(530800, 3),
- "6 days, 3 hours, 26 minutes 40 seconds")
-
- def test_style_4(self):
- """Test the style 4 of time_format."""
- self.assertEqual(utils.time_format(0, 4), "0 seconds")
- self.assertEqual(utils.time_format(28, 4), "28 seconds")
- self.assertEqual(utils.time_format(92, 4), "a minute")
- self.assertEqual(utils.time_format(300, 4), "5 minutes")
- self.assertEqual(utils.time_format(660, 4), "11 minutes")
- self.assertEqual(utils.time_format(3600, 4), "an hour")
- self.assertEqual(utils.time_format(3725, 4), "an hour")
- self.assertEqual(utils.time_format(86350, 4), "23 hours")
- self.assertEqual(utils.time_format(86800, 4), "a day")
- self.assertEqual(utils.time_format(130800, 4), "a day")
- self.assertEqual(utils.time_format(530800, 4), "6 days")
- self.assertEqual(utils.time_format(3030800, 4), "a month")
- self.assertEqual(utils.time_format(7030800, 4), "2 months")
- self.assertEqual(utils.time_format(40030800, 4), "a year")
- self.assertEqual(utils.time_format(90030800, 4), "2 years")
-
- def test_unknown_format(self):
- """Test that unknown formats raise exceptions."""
- self.assertRaises(ValueError, utils.time_format, 0, 5)
- self.assertRaises(ValueError, utils.time_format, 0, "u")
diff --git a/evennia/utils/tests/__init__.py b/evennia/utils/tests/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/evennia/utils/tests/data/__init__.py b/evennia/utils/tests/data/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/evennia/utils/evform_test.py b/evennia/utils/tests/data/evform_example.py
similarity index 100%
rename from evennia/utils/evform_test.py
rename to evennia/utils/tests/data/evform_example.py
diff --git a/evennia/utils/test_prototypes.py b/evennia/utils/tests/data/prototypes_example.py
similarity index 100%
rename from evennia/utils/test_prototypes.py
rename to evennia/utils/tests/data/prototypes_example.py
diff --git a/evennia/utils/tests/test_evform.py b/evennia/utils/tests/test_evform.py
new file mode 100644
index 0000000000..e6a0d26049
--- /dev/null
+++ b/evennia/utils/tests/test_evform.py
@@ -0,0 +1,55 @@
+"""
+Unit tests for the EvForm text form generator
+
+"""
+from django.test import TestCase
+from evennia.utils import evform
+
+
+class TestEvForm(TestCase):
+ def test_form(self):
+ self.maxDiff = None
+ self.assertEqual(evform._test(),
+ u'.------------------------------------------------.\n'
+ u'| |\n'
+ u'| Name: \x1b[0m\x1b[1m\x1b[32mTom\x1b[1m\x1b[32m \x1b'
+ u'[1m\x1b[32mthe\x1b[1m\x1b[32m \x1b[0m \x1b[0m '
+ u'Account: \x1b[0m\x1b[1m\x1b[33mGriatch '
+ u'\x1b[0m\x1b[0m\x1b[1m\x1b[32m\x1b[1m\x1b[32m\x1b[1m\x1b[32m\x1b[1m\x1b[32m\x1b[0m\x1b[0m '
+ u'|\n'
+ u'| \x1b[0m\x1b[1m\x1b[32mBouncer\x1b[0m \x1b[0m |\n'
+ u'| |\n'
+ u' >----------------------------------------------<\n'
+ u'| |\n'
+ u'| Desc: \x1b[0mA sturdy \x1b[0m \x1b[0m'
+ u' STR: \x1b[0m12 \x1b[0m\x1b[0m\x1b[0m\x1b[0m'
+ u' DEX: \x1b[0m10 \x1b[0m\x1b[0m\x1b[0m\x1b[0m |\n'
+ u'| \x1b[0mfellow\x1b[0m \x1b[0m'
+ u' INT: \x1b[0m5 \x1b[0m\x1b[0m\x1b[0m\x1b[0m'
+ u' STA: \x1b[0m18 \x1b[0m\x1b[0m\x1b[0m\x1b[0m |\n'
+ u'| \x1b[0m \x1b[0m'
+ u' LUC: \x1b[0m10 \x1b[0m\x1b[0m\x1b[0m'
+ u' MAG: \x1b[0m3 \x1b[0m\x1b[0m\x1b[0m |\n'
+ u'| |\n'
+ u' >----------.-----------------------------------<\n'
+ u'| | |\n'
+ u'| \x1b[0mHP\x1b[0m|\x1b[0mMV \x1b[0m|\x1b[0mMP\x1b[0m '
+ u'| \x1b[0mSkill \x1b[0m|\x1b[0mValue \x1b[0m'
+ u'|\x1b[0mExp \x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m |\n'
+ u'| ~~+~~~+~~ | ~~~~~~~~~~~+~~~~~~~~~~+~~~~~~~~~~~ |\n'
+ u'| \x1b[0m**\x1b[0m|\x1b[0m***\x1b[0m\x1b[0m|\x1b[0m**\x1b[0m\x1b[0m '
+ u'| \x1b[0mShooting \x1b[0m|\x1b[0m12 \x1b[0m'
+ u'|\x1b[0m550/1200 \x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m |\n'
+ u'| \x1b[0m \x1b[0m|\x1b[0m**\x1b[0m \x1b[0m|\x1b[0m*\x1b[0m \x1b[0m '
+ u'| \x1b[0mHerbalism \x1b[0m|\x1b[0m14 \x1b[0m'
+ u'|\x1b[0m990/1400 \x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m |\n'
+ u'| \x1b[0m \x1b[0m|\x1b[0m \x1b[0m|\x1b[0m \x1b[0m '
+ u'| \x1b[0mSmithing \x1b[0m|\x1b[0m9 \x1b[0m'
+ u'|\x1b[0m205/900 \x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m\x1b[0m |\n'
+ u'| | |\n'
+ u' -----------`-------------------------------------\n')
+
+ def test_ansi_escape(self):
+ # note that in a msg() call, the result would be the correct |-----,
+ # in a print, ansi only gets called once, so ||----- is the result
+ self.assertEqual(unicode(evform.EvForm(form={"FORM": "\n||-----"})), "||-----")
diff --git a/evennia/utils/tests/test_evmenu.py b/evennia/utils/tests/test_evmenu.py
new file mode 100644
index 0000000000..4436fdccd6
--- /dev/null
+++ b/evennia/utils/tests/test_evmenu.py
@@ -0,0 +1,25 @@
+"""
+Unit tests for the EvMenu system
+
+TODO: This need expansion.
+
+"""
+
+from django.test import TestCase
+from evennia.utils import evmenu
+from mock import Mock
+
+
+class TestEvMenu(TestCase):
+ "Run the EvMenu testing."
+
+ def setUp(self):
+ self.caller = Mock()
+ self.caller.msg = Mock()
+ self.menu = evmenu.EvMenu(self.caller, "evennia.utils.evmenu", startnode="test_start_node",
+ persistent=True, cmdset_mergetype="Replace", testval="val",
+ testval2="val2")
+
+ def test_kwargsave(self):
+ self.assertTrue(hasattr(self.menu, "testval"))
+ self.assertTrue(hasattr(self.menu, "testval2"))
diff --git a/evennia/utils/tests/test_tagparsing.py b/evennia/utils/tests/test_tagparsing.py
new file mode 100644
index 0000000000..a2f07af204
--- /dev/null
+++ b/evennia/utils/tests/test_tagparsing.py
@@ -0,0 +1,277 @@
+"""
+Unit tests for all sorts of inline text-tag parsing, like ANSI, html conversion, inlinefuncs etc
+
+"""
+import re
+from django.test import TestCase
+from evennia.utils.ansi import ANSIString
+from evennia.utils.text2html import TextToHTMLparser
+from evennia.utils import inlinefuncs
+
+
+class ANSIStringTestCase(TestCase):
+ def checker(self, ansi, raw, clean):
+ """
+ Verifies the raw and clean strings of an ANSIString match expected
+ output.
+ """
+ self.assertEqual(unicode(ansi.clean()), clean)
+ self.assertEqual(unicode(ansi.raw()), raw)
+
+ def table_check(self, ansi, char, code):
+ """
+ Verifies the indexes in an ANSIString match what they should.
+ """
+ self.assertEqual(ansi._char_indexes, char)
+ self.assertEqual(ansi._code_indexes, code)
+
+ def test_instance(self):
+ """
+ Make sure the ANSIString is always constructed correctly.
+ """
+ clean = u'This isA|r testTest'
+ encoded = u'\x1b[1m\x1b[32mThis is\x1b[1m\x1b[31mA|r test\x1b[0mTest\x1b[0m'
+ target = ANSIString(r'|gThis is|rA||r test|nTest|n')
+ char_table = [9, 10, 11, 12, 13, 14, 15, 25, 26, 27, 28, 29, 30, 31, 32, 37, 38, 39, 40]
+ code_table = [0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 17, 18, 19, 20, 21, 22, 23, 24, 33, 34, 35, 36, 41, 42, 43, 44]
+ self.checker(target, encoded, clean)
+ self.table_check(target, char_table, code_table)
+ self.checker(ANSIString(target), encoded, clean)
+ self.table_check(ANSIString(target), char_table, code_table)
+ self.checker(ANSIString(encoded, decoded=True), encoded, clean)
+ self.table_check(ANSIString(encoded, decoded=True), char_table,
+ code_table)
+ self.checker(ANSIString('Test'), u'Test', u'Test')
+ self.table_check(ANSIString('Test'), [0, 1, 2, 3], [])
+ self.checker(ANSIString(''), u'', u'')
+
+ def test_slice(self):
+ """
+ Verifies that slicing an ANSIString results in expected color code
+ distribution.
+ """
+ target = ANSIString(r'|gTest|rTest|n')
+ result = target[:3]
+ self.checker(result, u'\x1b[1m\x1b[32mTes', u'Tes')
+ result = target[:4]
+ self.checker(result, u'\x1b[1m\x1b[32mTest\x1b[1m\x1b[31m', u'Test')
+ result = target[:]
+ self.checker(
+ result,
+ u'\x1b[1m\x1b[32mTest\x1b[1m\x1b[31mTest\x1b[0m',
+ u'TestTest')
+ result = target[:-1]
+ self.checker(
+ result,
+ u'\x1b[1m\x1b[32mTest\x1b[1m\x1b[31mTes',
+ u'TestTes')
+ result = target[0:0]
+ self.checker(
+ result,
+ u'',
+ u'')
+
+ def test_split(self):
+ """
+ Verifies that re.split and .split behave similarly and that color
+ codes end up where they should.
+ """
+ target = ANSIString("|gThis is |nA split string|g")
+ first = (u'\x1b[1m\x1b[32mThis is \x1b[0m', u'This is ')
+ second = (u'\x1b[1m\x1b[32m\x1b[0m split string\x1b[1m\x1b[32m',
+ u' split string')
+ re_split = re.split('A', target)
+ normal_split = target.split('A')
+ self.assertEqual(re_split, normal_split)
+ self.assertEqual(len(normal_split), 2)
+ self.checker(normal_split[0], *first)
+ self.checker(normal_split[1], *second)
+
+ def test_join(self):
+ """
+ Verify that joining a set of ANSIStrings works.
+ """
+ # This isn't the desired behavior, but the expected one. Python
+ # concatenates the in-memory representation with the built-in string's
+ # join.
+ l = [ANSIString("|gTest|r") for _ in range(0, 3)]
+ # Force the generator to be evaluated.
+ result = "".join(l)
+ self.assertEqual(unicode(result), u'TestTestTest')
+ result = ANSIString("").join(l)
+ self.checker(result, u'\x1b[1m\x1b[32mTest\x1b[1m\x1b[31m\x1b[1m\x1b'
+ u'[32mTest\x1b[1m\x1b[31m\x1b[1m\x1b[32mTest'
+ u'\x1b[1m\x1b[31m', u'TestTestTest')
+
+ def test_len(self):
+ """
+ Make sure that length reporting on ANSIStrings does not include
+ ANSI codes.
+ """
+ self.assertEqual(len(ANSIString('|gTest|n')), 4)
+
+ def test_capitalize(self):
+ """
+ Make sure that capitalization works. This is the simplest of the
+ _transform functions.
+ """
+ target = ANSIString('|gtest|n')
+ result = u'\x1b[1m\x1b[32mTest\x1b[0m'
+ self.checker(target.capitalize(), result, u'Test')
+
+ def test_mxp_agnostic(self):
+ """
+ Make sure MXP tags are not treated like ANSI codes, but normal text.
+ """
+ mxp1 = "|lclook|ltat|le"
+ mxp2 = "Start to |lclook here|ltclick somewhere here|le first"
+ self.assertEqual(15, len(ANSIString(mxp1)))
+ self.assertEqual(53, len(ANSIString(mxp2)))
+ # These would indicate an issue with the tables.
+ self.assertEqual(len(ANSIString(mxp1)), len(ANSIString(mxp1).split("\n")[0]))
+ self.assertEqual(len(ANSIString(mxp2)), len(ANSIString(mxp2).split("\n")[0]))
+ self.assertEqual(mxp1, ANSIString(mxp1))
+ self.assertEqual(mxp2, unicode(ANSIString(mxp2)))
+
+ def test_add(self):
+ """
+ Verify concatenation works correctly.
+ """
+ a = ANSIString("|gTest")
+ b = ANSIString("|cString|n")
+ c = a + b
+ result = u'\x1b[1m\x1b[32mTest\x1b[1m\x1b[36mString\x1b[0m'
+ self.checker(c, result, u'TestString')
+ char_table = [9, 10, 11, 12, 22, 23, 24, 25, 26, 27]
+ code_table = [0, 1, 2, 3, 4, 5, 6, 7, 8, 13, 14, 15, 16, 17, 18, 19, 20, 21, 28, 29, 30, 31]
+ self.table_check(c, char_table, code_table)
+
+ def test_strip(self):
+ """
+ Test the ansi-aware .strip() methods
+ """
+ a = ANSIString(" |r Test of stuff |b with spaces |n ")
+ b = ANSIString("|r|b")
+ self.assertEqual(a.strip(), ANSIString("|rTest of stuff |b with spaces|n"))
+ self.assertEqual(a.lstrip(), ANSIString("|rTest of stuff |b with spaces |n "))
+ self.assertEqual(a.rstrip(), ANSIString(" |r Test of stuff |b with spaces|n"))
+ self.assertEqual(b.strip(), b)
+
+
+class TestTextToHTMLparser(TestCase):
+ def setUp(self):
+ self.parser = TextToHTMLparser()
+
+ def tearDown(self):
+ del self.parser
+
+ def test_url_scheme_ftp(self):
+ self.assertEqual(self.parser.convert_urls('ftp.example.com'),
+ 'ftp.example.com')
+
+ def test_url_scheme_www(self):
+ self.assertEqual(self.parser.convert_urls('www.example.com'),
+ 'www.example.com')
+
+ def test_url_scheme_ftpproto(self):
+ self.assertEqual(self.parser.convert_urls('ftp://ftp.example.com'),
+ 'ftp://ftp.example.com')
+
+ def test_url_scheme_http(self):
+ self.assertEqual(self.parser.convert_urls('http://example.com'),
+ 'http://example.com')
+
+ def test_url_scheme_https(self):
+ self.assertEqual(self.parser.convert_urls('https://example.com'),
+ 'https://example.com')
+
+ def test_url_chars_slash(self):
+ self.assertEqual(self.parser.convert_urls('www.example.com/homedir'),
+ 'www.example.com/homedir')
+
+ def test_url_chars_colon(self):
+ self.assertEqual(self.parser.convert_urls('https://example.com:8000/login/'),
+ ''
+ 'https://example.com:8000/login/')
+
+ def test_url_chars_querystring(self):
+ self.assertEqual(self.parser.convert_urls('https://example.com/submitform?field1=val1+val3&field2=val2'),
+ ''
+ 'https://example.com/submitform?field1=val1+val3&field2=val2')
+
+ def test_url_chars_anchor(self):
+ self.assertEqual(self.parser.convert_urls('http://www.example.com/menu#section_1'),
+ ''
+ 'http://www.example.com/menu#section_1')
+
+ def test_url_chars_exclam(self):
+ self.assertEqual(self.parser.convert_urls('https://groups.google.com/forum/'
+ '?fromgroups#!categories/evennia/ainneve'),
+ 'https://groups.google.com/forum/?fromgroups#!categories/evennia/ainneve')
+
+ def test_url_edge_leadingw(self):
+ self.assertEqual(self.parser.convert_urls('wwww.example.com'),
+ 'wwww.example.com')
+
+ def test_url_edge_following_period_eol(self):
+ self.assertEqual(self.parser.convert_urls('www.example.com.'),
+ 'www.example.com.')
+
+ def test_url_edge_following_period(self):
+ self.assertEqual(self.parser.convert_urls('see www.example.com. '),
+ 'see www.example.com. ')
+
+ def test_url_edge_brackets(self):
+ self.assertEqual(self.parser.convert_urls('[http://example.com/]'),
+ '[http://example.com/]')
+
+ def test_url_edge_multiline(self):
+ self.assertEqual(self.parser.convert_urls(' * http://example.com/info\n * bullet'),
+ ' * '
+ 'http://example.com/info\n * bullet')
+
+ def test_url_edge_following_htmlentity(self):
+ self.assertEqual(self.parser.convert_urls('http://example.com/info<span>'),
+ 'http://example.com/info<span>')
+
+ def test_url_edge_surrounded_spans(self):
+ self.assertEqual(self.parser.convert_urls('http://example.com/'),
+ ''
+ 'http://example.com/')
+
+
+class TestInlineFuncs(TestCase):
+ """Test the nested inlinefunc module"""
+
+ def test_nofunc(self):
+ self.assertEqual(inlinefuncs.parse_inlinefunc(
+ "as$382ewrw w we w werw,|44943}"),
+ "as$382ewrw w we w werw,|44943}")
+
+ def test_incomplete(self):
+ self.assertEqual(inlinefuncs.parse_inlinefunc(
+ "testing $blah{without an ending."),
+ "testing $blah{without an ending.")
+
+ def test_single_func(self):
+ self.assertEqual(inlinefuncs.parse_inlinefunc(
+ "this is a test with $pad(centered, 20) text in it."),
+ "this is a test with centered text in it.")
+
+ def test_nested(self):
+ self.assertEqual(inlinefuncs.parse_inlinefunc(
+ "this $crop(is a test with $pad(padded, 20) text in $pad(pad2, 10) a crop, 80)"),
+ "this is a test with padded text in pad2 a crop")
+
+ def test_escaped(self):
+ self.assertEqual(inlinefuncs.parse_inlinefunc(
+ "this should be $pad('''escaped,''' and '''instead,''' cropped $crop(with a long,5) text., 80)"),
+ "this should be escaped, and instead, cropped with text. ")
+
+ def test_escaped2(self):
+ self.assertEqual(inlinefuncs.parse_inlinefunc(
+ 'this should be $pad("""escaped,""" and """instead,""" cropped $crop(with a long,5) text., 80)'),
+ "this should be escaped, and instead, cropped with text. ")
+
+
diff --git a/evennia/utils/tests/test_utils.py b/evennia/utils/tests/test_utils.py
new file mode 100644
index 0000000000..d2e42c4169
--- /dev/null
+++ b/evennia/utils/tests/test_utils.py
@@ -0,0 +1,188 @@
+"""
+Unit tests for the utilities of the evennia.utils.utils module.
+
+TODO: Not nearly all utilities are covered yet.
+
+"""
+
+from django.test import TestCase
+
+from evennia.utils.ansi import ANSIString
+from evennia.utils import utils
+
+
+class TestIsIter(TestCase):
+ def test_is_iter(self):
+ self.assertEqual(True, utils.is_iter([1, 2, 3, 4]))
+ self.assertEqual(False, utils.is_iter("This is not an iterable"))
+
+
+class TestCrop(TestCase):
+ def test_crop(self):
+ # No text, return no text
+ self.assertEqual("", utils.crop("", width=10, suffix="[...]"))
+ # Input length equal to max width, no crop
+ self.assertEqual("0123456789", utils.crop("0123456789", width=10, suffix="[...]"))
+ # Input length greater than max width, crop (suffix included in width)
+ self.assertEqual("0123[...]", utils.crop("0123456789", width=9, suffix="[...]"))
+ # Input length less than desired width, no crop
+ self.assertEqual("0123", utils.crop("0123", width=9, suffix="[...]"))
+ # Width too small or equal to width of suffix
+ self.assertEqual("012", utils.crop("0123", width=3, suffix="[...]"))
+ self.assertEqual("01234", utils.crop("0123456", width=5, suffix="[...]"))
+
+
+class TestDedent(TestCase):
+ def test_dedent(self):
+ # Empty string, return empty string
+ self.assertEqual("", utils.dedent(""))
+ # No leading whitespace
+ self.assertEqual("TestDedent", utils.dedent("TestDedent"))
+ # Leading whitespace, single line
+ self.assertEqual("TestDedent", utils.dedent(" TestDedent"))
+ # Leading whitespace, multi line
+ input_string = " hello\n world"
+ expected_string = "hello\nworld"
+ self.assertEqual(expected_string, utils.dedent(input_string))
+
+
+class TestListToString(TestCase):
+ """
+ Default function header from utils.py:
+ list_to_string(inlist, endsep="and", addquote=False)
+
+ Examples:
+ no endsep:
+ [1,2,3] -> '1, 2, 3'
+ with endsep=='and':
+ [1,2,3] -> '1, 2 and 3'
+ with addquote and endsep
+ [1,2,3] -> '"1", "2" and "3"'
+ """
+
+ def test_list_to_string(self):
+ self.assertEqual('1, 2, 3', utils.list_to_string([1, 2, 3], endsep=""))
+ self.assertEqual('"1", "2", "3"', utils.list_to_string([1, 2, 3], endsep="", addquote=True))
+ self.assertEqual('1, 2 and 3', utils.list_to_string([1, 2, 3]))
+ self.assertEqual('"1", "2" and "3"', utils.list_to_string([1, 2, 3], endsep="and", addquote=True))
+
+
+class TestMLen(TestCase):
+ """
+ Verifies that m_len behaves like len in all situations except those
+ where MXP may be involved.
+ """
+
+ def test_non_mxp_string(self):
+ self.assertEqual(utils.m_len('Test_string'), 11)
+
+ def test_mxp_string(self):
+ self.assertEqual(utils.m_len('|lclook|ltat|le'), 2)
+
+ def test_mxp_ansi_string(self):
+ self.assertEqual(utils.m_len(ANSIString('|lcl|gook|ltat|le|n')), 2)
+
+ def test_non_mxp_ansi_string(self):
+ self.assertEqual(utils.m_len(ANSIString('|gHello|n')), 5)
+
+ def test_list(self):
+ self.assertEqual(utils.m_len([None, None]), 2)
+
+ def test_dict(self):
+ self.assertEqual(utils.m_len({'hello': True, 'Goodbye': False}), 2)
+
+
+class TestTimeformat(TestCase):
+ """
+ Default function header from utils.py:
+ time_format(seconds, style=0)
+
+ """
+
+ def test_style_0(self):
+ """Test the style 0 of time_format."""
+ self.assertEqual(utils.time_format(0, 0), "00:00")
+ self.assertEqual(utils.time_format(28, 0), "00:00")
+ self.assertEqual(utils.time_format(92, 0), "00:01")
+ self.assertEqual(utils.time_format(300, 0), "00:05")
+ self.assertEqual(utils.time_format(660, 0), "00:11")
+ self.assertEqual(utils.time_format(3600, 0), "01:00")
+ self.assertEqual(utils.time_format(3725, 0), "01:02")
+ self.assertEqual(utils.time_format(86350, 0), "23:59")
+ self.assertEqual(utils.time_format(86800, 0), "1d 00:06")
+ self.assertEqual(utils.time_format(130800, 0), "1d 12:20")
+ self.assertEqual(utils.time_format(530800, 0), "6d 03:26")
+
+ def test_style_1(self):
+ """Test the style 1 of time_format."""
+ self.assertEqual(utils.time_format(0, 1), "0s")
+ self.assertEqual(utils.time_format(28, 1), "28s")
+ self.assertEqual(utils.time_format(92, 1), "1m")
+ self.assertEqual(utils.time_format(300, 1), "5m")
+ self.assertEqual(utils.time_format(660, 1), "11m")
+ self.assertEqual(utils.time_format(3600, 1), "1h")
+ self.assertEqual(utils.time_format(3725, 1), "1h")
+ self.assertEqual(utils.time_format(86350, 1), "23h")
+ self.assertEqual(utils.time_format(86800, 1), "1d")
+ self.assertEqual(utils.time_format(130800, 1), "1d")
+ self.assertEqual(utils.time_format(530800, 1), "6d")
+
+ def test_style_2(self):
+ """Test the style 2 of time_format."""
+ self.assertEqual(utils.time_format(0, 2), "0 minutes")
+ self.assertEqual(utils.time_format(28, 2), "0 minutes")
+ self.assertEqual(utils.time_format(92, 2), "1 minute")
+ self.assertEqual(utils.time_format(300, 2), "5 minutes")
+ self.assertEqual(utils.time_format(660, 2), "11 minutes")
+ self.assertEqual(utils.time_format(3600, 2), "1 hour, 0 minutes")
+ self.assertEqual(utils.time_format(3725, 2), "1 hour, 2 minutes")
+ self.assertEqual(utils.time_format(86350, 2), "23 hours, 59 minutes")
+ self.assertEqual(utils.time_format(86800, 2),
+ "1 day, 0 hours, 6 minutes")
+ self.assertEqual(utils.time_format(130800, 2),
+ "1 day, 12 hours, 20 minutes")
+ self.assertEqual(utils.time_format(530800, 2),
+ "6 days, 3 hours, 26 minutes")
+
+ def test_style_3(self):
+ """Test the style 3 of time_format."""
+ self.assertEqual(utils.time_format(0, 3), "")
+ self.assertEqual(utils.time_format(28, 3), "28 seconds")
+ self.assertEqual(utils.time_format(92, 3), "1 minute 32 seconds")
+ self.assertEqual(utils.time_format(300, 3), "5 minutes 0 seconds")
+ self.assertEqual(utils.time_format(660, 3), "11 minutes 0 seconds")
+ self.assertEqual(utils.time_format(3600, 3),
+ "1 hour, 0 minutes")
+ self.assertEqual(utils.time_format(3725, 3),
+ "1 hour, 2 minutes 5 seconds")
+ self.assertEqual(utils.time_format(86350, 3),
+ "23 hours, 59 minutes 10 seconds")
+ self.assertEqual(utils.time_format(86800, 3),
+ "1 day, 0 hours, 6 minutes 40 seconds")
+ self.assertEqual(utils.time_format(130800, 3),
+ "1 day, 12 hours, 20 minutes 0 seconds")
+ self.assertEqual(utils.time_format(530800, 3),
+ "6 days, 3 hours, 26 minutes 40 seconds")
+
+ def test_style_4(self):
+ """Test the style 4 of time_format."""
+ self.assertEqual(utils.time_format(0, 4), "0 seconds")
+ self.assertEqual(utils.time_format(28, 4), "28 seconds")
+ self.assertEqual(utils.time_format(92, 4), "a minute")
+ self.assertEqual(utils.time_format(300, 4), "5 minutes")
+ self.assertEqual(utils.time_format(660, 4), "11 minutes")
+ self.assertEqual(utils.time_format(3600, 4), "an hour")
+ self.assertEqual(utils.time_format(3725, 4), "an hour")
+ self.assertEqual(utils.time_format(86350, 4), "23 hours")
+ self.assertEqual(utils.time_format(86800, 4), "a day")
+ self.assertEqual(utils.time_format(130800, 4), "a day")
+ self.assertEqual(utils.time_format(530800, 4), "6 days")
+ self.assertEqual(utils.time_format(3030800, 4), "a month")
+ self.assertEqual(utils.time_format(7030800, 4), "2 months")
+ self.assertEqual(utils.time_format(40030800, 4), "a year")
+ self.assertEqual(utils.time_format(90030800, 4), "2 years")
+
+ def test_unknown_format(self):
+ """Test that unknown formats raise exceptions."""
+ self.assertRaises(ValueError, utils.time_format, 0, 5)
+ self.assertRaises(ValueError, utils.time_format, 0, "u")