Merge branch '2.4.5' of ssh://git.tasktools.org/tm/task into 2.4.5

This commit is contained in:
Paul Beckingham
2015-07-17 14:40:49 -04:00
82 changed files with 1436 additions and 1562 deletions

View File

@@ -5,6 +5,7 @@ How to Build Taskwarrior
will be utilizing C++11.
- libuuid
- gnutls (optional)
- python 2.7 or 3 (optional, for running the test suite)
Obtain and build code:
$ git clone https://git.tasktools.org/scm/tm/task.git task.git

View File

@@ -40,40 +40,40 @@ class TestAbbreviation(TestCase):
self.t = Task()
self.t.config("abbreviation.minimum", "1")
self.t(("add", "project:home", "priority:H", "hasattributes"))
self.t(("add", "noattributes"))
self.t("add project:home priority:H hasattributes")
self.t("add noattributes")
def verify_attibute(self, expr):
code, out, err = self.t(("list", expr))
def verify_attribute(self, expr):
code, out, err = self.t("list {0}".format(expr))
self.assertIn("hasattributes", out, msg=expr + " hasattributes")
self.assertNotIn("noattributes", out, msg=expr + " noattributes")
self.assertIn("hasattributes", out)
self.assertNotIn("noattributes", out)
def test_attribute_abbreviations(self):
"Test project attribute abbrevations"
self.verify_attibute("project:home")
self.verify_attibute("projec:home")
self.verify_attibute("proje:home")
self.verify_attibute("proj:home")
self.verify_attibute("pro:home")
self.verify_attribute("project:home")
self.verify_attribute("projec:home")
self.verify_attribute("proje:home")
self.verify_attribute("proj:home")
self.verify_attribute("pro:home")
def test_uda_abbreviations(self):
"Test uda attribute abbrevations"
# NOTE This will be an UDA when TW-1541 is closed, for now it's just
# one more attribute
self.verify_attibute("priority:H")
self.verify_attibute("priorit:H")
self.verify_attibute("priori:H")
self.verify_attibute("prior:H")
self.verify_attibute("prio:H")
self.verify_attibute("pri:H")
self.verify_attribute("priority:H")
self.verify_attribute("priorit:H")
self.verify_attribute("priori:H")
self.verify_attribute("prior:H")
self.verify_attribute("prio:H")
self.verify_attribute("pri:H")
def verify_command(self, cmd):
code, out, err = self.t((cmd,))
code, out, err = self.t(cmd)
self.assertIn("MIT license", out, msg=cmd)
self.assertIn("MIT license", out)
def test_command_abbreviations(self):
"Test version command abbrevations"

View File

@@ -39,23 +39,23 @@ class TestAppend(TestCase):
def setUp(self):
"""Executed before each test in the class"""
self.t = Task()
self.t(("add", "foo"))
self.t("add foo")
def test_append(self):
"""Add a task and then append more description"""
code, out, err = self.t(("1", "append", "bar"))
code, out, err = self.t("1 append bar")
expected = "Appended 1 task."
self.assertIn(expected, out)
code, out, err = self.t(("info", "1"))
code, out, err = self.t("info 1")
expected = "Description\s+foo\sbar\n"
self.assertRegexpMatches(out, expected)
def test_append_error_on_empty(self):
"""Should cause an error when nothing is appended"""
code, out, err = self.t.runError(("1", "append"))
code, out, err = self.t.runError("1 append")
expected = "Additional text must be provided."
self.assertIn(expected, err)
@@ -72,14 +72,14 @@ class TestBug440(TestCase):
def test_subst_and_append_at_once(self):
"""Simultaneous substitution and append"""
self.t(("add", "Foo"))
self.t(("add", "Foo"))
self.t("add Foo")
self.t("add Foo")
self.t(("1", "append", "/Foo/Bar/", "Appendtext"))
self.t(("2", "append", "Appendtext", "/Foo/Bar/"))
self.t("1 append /Foo/Bar/ Appendtext")
self.t("2 append Appendtext /Foo/Bar/")
code1, out1, err1 = self.t(("1", "ls"))
code2, out2, err2 = self.t(("2", "ls"))
code1, out1, err1 = self.t("1 ls")
code2, out2, err2 = self.t("2 ls")
self.assertNotIn("Foo", out1)
self.assertRegexpMatches(out1, "\w+ Appendtext")

View File

@@ -41,22 +41,22 @@ class TestIDPosition(TestCase):
"""Executed once before any test in the class"""
cls.t = Task()
cls.t(("add", "one"))
cls.t(("add", "two"))
cls.t("add one")
cls.t("add two")
def test_id_read_cmd(self):
"""Test id before and after read command"""
code, out, err = self.t(("1", "info"))
code, out, err = self.t("1 info")
self.assertIn("one", out)
self.assertNotIn("two", out)
code, out, err = self.t(("info", "1"))
code, out, err = self.t("info 1")
self.assertIn("one", out)
self.assertNotIn("two", out)
def test_id_write_cmd(self):
"""Test id before write command"""
code, out, err = self.t(("2", "done"))
code, out, err = self.t("2 done")
self.assertIn("Completed task 2", out)

View File

@@ -165,16 +165,17 @@ class Task(object):
# Enable nicer-looking calls by allowing plain strings
try:
# Python 2.x
if isinstance(args, basestring):
args = shlex.split(args)
type_check = basestring
except NameError:
# Python 3.x
if isinstance(args, str):
args = shlex.split(args)
type_check = str
if isinstance(args, type_check):
args = shlex.split(args)
return args
def runSuccess(self, args=(), input=None, merge_streams=False,
def runSuccess(self, args="", input=None, merge_streams=False,
timeout=5):
"""Invoke task with given arguments and fail if exit code != 0
@@ -279,7 +280,7 @@ class Task(object):
which should be the output of any previous process that failed.
"""
try:
output = self.runSuccess(("diag",))
output = self.runSuccess("diag")
except CommandError as e:
# If task diag failed add the error to stderr
output = (e.code, None, str(e))

View File

@@ -46,14 +46,14 @@ class TestBug1006(TestCase):
self.t.config("verbose", "affected")
def initial_tasks(self):
self.t(("add", "des"))
self.t(("1", "annotate", "des"))
self.t("add des")
self.t("1 annotate des")
def test_completion_of_des_inactive(self):
"Check that the completion is inactive in task descriptions"
self.initial_tasks()
code, out, err = self.t(("1", "info"))
code, out, err = self.t("1 info")
expected = "Description +des\n"
errormsg = "Attribute not completed in description"
@@ -66,7 +66,7 @@ class TestBug1006(TestCase):
"Check that the completion works when needed"
self.initial_tasks()
code, out, err = self.t(("des:des",))
code, out, err = self.t("des:des")
errormsg = "Task found using its description"
self.assertIn("1 task", out, msg=errormsg)
@@ -74,8 +74,8 @@ class TestBug1006(TestCase):
def test_accented_chars(self):
"Check that é in entrée remains untouched"
self.t(("add", "entrée interdite"))
code, out, err = self.t(("list", "interdite"))
self.t("add entrée interdite")
code, out, err = self.t("list interdite")
errormsg = "'entrée' left intact"
self.assertIn("entrée interdite", out, msg=errormsg)

View File

@@ -46,24 +46,24 @@ class TestBug1031(TestCase):
def test_alias_to(self):
"""alias working as expected: 'from' -> 'to'"""
self.t(("add", "from"))
code, out, err = self.t(("1", "info"))
self.t("add from")
code, out, err = self.t("1 info")
expected = "Description\s+to"
self.assertRegexpMatches(out, expected)
def test_alias_to_to(self):
"""alias working as expected: 'from -- to' -> 'to to'"""
self.t(("add", "from", "--", "to"))
code, out, err = self.t(("1", "info"))
self.t("add from -- to")
code, out, err = self.t("1 info")
expected = "Description\s+to to"
self.assertRegexpMatches(out, expected)
def test_alias_to_from(self):
"""alias working as expected: 'to -- from' -> 'to from'"""
self.t(("add", "to", "--", "from"))
code, out, err = self.t(("1", "info"))
self.t("add to -- from")
code, out, err = self.t("1 info")
expected = "Description\s+to from"
self.assertRegexpMatches(out, expected)

View File

@@ -45,16 +45,16 @@ class TestBug1036(TestCase):
def test_until_may_modify(self):
"""check that until attribute may be modified"""
self.t(("add", "test"))
code, out, err = self.t(("1", "mod", "until:1/1/2020"))
self.t("add test")
code, out, err = self.t("1 mod until:1/1/2020")
expected = "Modifying task 1 'test'."
self.assertIn(expected, out)
def test_may_modify_on_until(self):
"""check that task with until attribute set may be modified"""
self.t(("add", "test", "until:1/1/2020"))
code, out, err = self.t(("1", "mod", "/test/Hello/"))
self.t("add test until:1/1/2020")
code, out, err = self.t("1 mod /test/Hello/")
expected = "Modifying task 1 'Hello'."
self.assertIn(expected, out)

View File

@@ -53,16 +53,16 @@ class TestBug1063(TestCase):
Reported as bug 1063
"""
self.t(("add", "four", "foo:4"))
self.t(("add", "one", "foo:1"))
self.t(("add", "three", "foo:3"))
self.t(("add", "two", "foo:2"))
self.t("add four foo:4")
self.t("add one foo:1")
self.t("add three foo:3")
self.t("add two foo:2")
code, out, err = self.t(("bar",))
code, out, err = self.t("bar")
expected = re.compile("4.+3.+2.+1", re.DOTALL) # dot matches \n too
self.assertRegexpMatches(out, expected)
code, out, err = self.t(("bar", "rc.report.bar.sort=foo+"))
code, out, err = self.t("bar rc.report.bar.sort=foo+")
expected = re.compile("1.+2.+3.+4", re.DOTALL) # dot matches \n too
self.assertRegexpMatches(out, expected)

View File

@@ -43,15 +43,12 @@ class TestBug1254(TestCase):
def test_no_segmentation_fault_calc_negative_multiplication(self):
"""calc can multiply zero and negative numbers
"""
args = ("calc", "0*-1")
self.run_command(args)
self.run_command("calc 0*-1")
def test_calc_positive_multiplication(self):
"""calc can multiply negative zero and positive
"""
args = ("calc", "0*1")
self.run_command(args)
self.run_command("calc 0*1")
def run_command(self, args):
code, out, err = self.t(args)

View File

@@ -44,12 +44,9 @@ class TestBug1267(TestCase):
"""
project = "MakePudding"
args = ["rc.default.project={0}".format(project), "add",
"proj:", "Add cream"]
self.t(args)
self.t("rc.default.project={0} add proj: 'Add cream'".format(project))
args = ("ls",)
code, out, err = self.t(args, merge_streams=False)
code, out, err = self.t("ls")
self.assertNotIn(project, out)
@@ -60,11 +57,9 @@ class TestBug1267(TestCase):
self.t.config("default.project", project)
args = ("add", "proj:", "Add cream")
self.t(args)
self.t("add proj: 'Add cream'")
args = ("ls",)
code, out, err = self.t(args, merge_streams=False)
code, out, err = self.t("ls")
self.assertNotIn(project, out)

View File

@@ -40,21 +40,16 @@ class BaseTestBug360(TestCase):
def setUp(self):
"""Executed before each test in the class"""
self.t = Task()
args = ("add", "foo", "due:tomorrow", "recur:daily")
self.t(args)
self.t("add foo due:tomorrow recur:daily")
# TODO: Add explanation why this line is necessary
args = ("ls",)
self.t(args)
self.t("ls")
class TestBug360RemovalError(BaseTestBug360):
def test_modify_recursive_project(self):
"""Modifying a recursive task by adding project: also modifies parent
"""
commands = "y\n"
args = ("1", "modify", "project:bar")
code, out, err = self.t(args, commands)
code, out, err = self.t("1 modify project:bar", input="y\n")
expected = "Modified 2 tasks."
self.assertIn(expected, out)
@@ -66,9 +61,8 @@ class TestBug360RemovalError(BaseTestBug360):
"""
# TODO Removing recur: from a recurring task should also remove imask
# and parent.
args = ("2", "modify", "recur:")
code, out, err = self.t.runError(args)
code, out, err = self.t.runError("2 modify recur:")
# Expected non zero exit-code
self.assertEqual(code, 2)
@@ -80,9 +74,7 @@ class TestBug360RemovalError(BaseTestBug360):
"""
# TODO Removing due: from a recurring task should also remove recur,
# imask and parent
args = ("2", "modify", "due:")
code, out, err = self.t.runError(args)
code, out, err = self.t.runError("2 modify due:")
# Expected non zero exit-code
self.assertEqual(code, 2)
@@ -96,13 +88,12 @@ class TestBug360AllowedChanges(BaseTestBug360):
# Also do setUp from BaseTestBug360
super(TestBug360AllowedChanges, self).setUp()
self.t(("add", "nonrecurring", "due:today"))
self.t("add nonrecurring due:today")
def test_allow_modify_due_in_nonrecurring(self):
"""Allow modifying due date in non recurring task"""
# Retrieve the id of the non recurring task
args = ("ls",)
code, out, err = self.t(args)
code, out, err = self.t("ls")
expected = "2 tasks"
self.assertIn(expected, out)
@@ -110,8 +101,7 @@ class TestBug360AllowedChanges(BaseTestBug360):
# NOTE: raw python string r"" avoids having to escape backslashes
id = re.search(r"(\d+)\s.+\snonrecurring", out).group(1)
args = (id, "modify", "due:")
code, out, err = self.t(args)
code, out, err = self.t((id, "modify", "due:"))
expected = "Modified 1 task."
self.assertIn(expected, out)

View File

@@ -41,10 +41,10 @@ class TestBug425(TestCase):
def test_bug425(self):
"""parser interpret 'in' in description"""
self.t(("add", "Foo"))
self.t(("1", "modify", "Bar in Bar"))
self.t("add Foo")
self.t("1 modify Bar in Bar")
code, out, err = self.t(("1", "ls"))
code, out, err = self.t("1 ls")
self.assertRegexpMatches(out, "1\s+Bar in Bar")

View File

@@ -42,10 +42,10 @@ class TestBug441(TestCase):
def test_bad_colon_replacement(self):
"""Substitution containing a colon"""
self.t(("add", "one two three"))
self.t(("1", "modify", "/two/two:/"))
self.t("add one two three")
self.t("1 modify /two/two:/")
code, out, err = self.t(("ls",))
code, out, err = self.t("ls")
self.assertIn("one two: three", out)

View File

@@ -53,14 +53,14 @@ class TestAnnotation(TestCase):
"""Verify filterless annotation is trapped, declined"""
self.t("add foo")
code, out, err = self.t.runError(("annotate", "bar"), input="no\n")
code, out, err = self.t.runError("annotate bar", input="no\n")
self.assertIn("Command prevented from running", err)
self.assertNotIn("Command prevented from running", out)
def test_filterless_annotate(self):
"""Verify filterless annotation is trapped, overridden"""
self.t("add foo")
code, out, err = self.t(("annotate", "bar"), input="yes\n")
code, out, err = self.t("annotate bar", input="yes\n")
self.assertNotIn("Command prevented from running", err)
self.assertNotIn("Command prevented from running", out)

View File

@@ -44,12 +44,12 @@ class TestCLI(TestCase):
def test_quoted_args_remain_intact(self):
"""Quoted arguments should remain unmolested."""
self.t(("add", "'a/b'"))
code, out, err = self.t(("_get", "1.description"))
self.t("add 'a/b'")
code, out, err = self.t("_get 1.description")
self.assertIn("a/b", out)
self.t(("add", "'1-2'"))
code, out, err = self.t(("_get", "2.description"))
self.t("add '1-2'")
code, out, err = self.t("_get 2.description")
self.assertIn("1-2", out)

View File

@@ -45,20 +45,20 @@ class TestAliasesCompletion(TestCase):
def test__aliases(self):
"""samplealias in _aliases"""
code, out, err = self.t(("_aliases",))
code, out, err = self.t("_aliases")
self.assertIn("samplealias", out)
def test__commands(self):
"""samplealias not in _commands"""
code, out, err = self.t(("_commands",))
code, out, err = self.t("_commands")
self.assertIn("information", out)
self.assertNotIn("samplealias", out)
def test__zshcommands(self):
"""samplealias not in _zshcommands"""
code, out, err = self.t(("_zshcommands",))
code, out, err = self.t("_zshcommands")
self.assertIn("information", out)
self.assertNotIn("samplealias", out)

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -36,6 +36,7 @@ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from basetest import Task, TestCase
class ContextManagementTest(TestCase):
def setUp(self):
self.t = Task()
@@ -45,10 +46,9 @@ class ContextManagementTest(TestCase):
Test simple context definition.
"""
output = self.t(('context', 'define', 'work', 'project:Work'))[1]
code, out, err = self.t('context define work project:Work')
# Assert successful output
self.assertIn("Context 'work' defined.", output)
self.assertIn("Context 'work' defined.", out)
# Assert the config contains context definition
self.assertIn('context.work=project:Work\n', self.t.taskrc_content)
@@ -62,11 +62,10 @@ class ContextManagementTest(TestCase):
Test re-defining the context with the same definition.
"""
self.t(('context', 'define', 'work', 'project:Work'))
output = self.t(('context', 'define', 'work', 'project:Work'))[1]
self.t('context define work project:Work')
code, out, err = self.t('context define work project:Work')
# Assert successful output
self.assertIn("Context 'work' defined.", output)
self.assertIn("Context 'work' defined.", out)
# Assert the config contains context definition
self.assertIn('context.work=project:Work\n', self.t.taskrc_content)
@@ -80,11 +79,10 @@ class ContextManagementTest(TestCase):
Test re-defining the context with different definition.
"""
self.t(('context', 'define', 'work', 'project:Work'))
output = self.t(('context', 'define', 'work', '+work'))[1]
self.t('context define work project:Work')
code, out, err = self.t('context define work +work')
# Assert successful output
self.assertIn("Context 'work' defined.", output)
self.assertIn("Context 'work' defined.", out)
# Assert the config does not contain the old context definition
self.assertNotIn('context.work=project:Work\n', self.t.taskrc_content)
@@ -101,11 +99,10 @@ class ContextManagementTest(TestCase):
Test simple context deletion.
"""
self.t(('context', 'define', 'work', 'project:Work'))
output = self.t(('context', 'delete', 'work'))[1]
self.t('context define work project:Work')
code, out, err = self.t('context delete work')
# Assert correct output
self.assertIn("Context 'work' deleted.", output)
self.assertIn("Context 'work' deleted.", out)
# Assert that taskrc does not countain context work definition
self.assertFalse(any('context.work=' in line for line in self.t.taskrc_content))
@@ -115,10 +112,9 @@ class ContextManagementTest(TestCase):
Test deletion of undefined context.
"""
output = self.t.runError(('context', 'delete', 'work'))[1]
code, out, err = self.t.runError('context delete work')
# Assert correct output
self.assertIn("Context 'work' not deleted.", output)
self.assertIn("Context 'work' not deleted.", out)
# Assert that taskrc does not countain context work definition
self.assertFalse(any('context.work=' in line for line in self.t.taskrc_content))
@@ -128,19 +124,18 @@ class ContextManagementTest(TestCase):
Test that context is unset if its definition has been removed.
"""
self.t(('context', 'define', 'work', 'project:Work'))
self.t(('context', 'work'))
output = self.t(('context', 'delete', 'work'))[1]
self.t('context define work project:Work')
self.t('context work')
code, out, err = self.t('context delete work')
# Assert correct output
self.assertIn("Context 'work' deleted.", output)
self.assertIn("Context 'work' deleted.", out)
# Assert that taskrc does not countain context work definition
self.assertFalse(any('context.work=' in line for line in self.t.taskrc_content))
# Aseert that the context is not set
output = self.t(('context', 'show'))[1]
self.assertIn('No context is currently applied.', output)
code, out, err = self.t('context show')
self.assertIn('No context is currently applied.', out)
self.assertFalse(any(re.search("^context=", line) for line in self.t.taskrc_content))
def test_context_list_active(self):
@@ -148,30 +143,30 @@ class ContextManagementTest(TestCase):
Test the 'context list' command.
"""
self.t(('context', 'define', 'work', 'project:Work'))
self.t(('context', 'define', 'home', '+home'))
self.t(('context', 'home'))
self.t('context define work project:Work')
self.t('context define home +home')
self.t('context home')
output = self.t(('context', 'list'))[1]
code, out, err = self.t('context list')
contains_work = lambda line: 'work' in line and 'project:Work' in line and 'no' in line
contains_home = lambda line: 'home' in line and '+home' in line and 'yes' in line
# Assert that output contains work and home context definitions exactly
# once
self.assertEqual(len(filter(contains_work, output.splitlines())), 1)
self.assertEqual(len(filter(contains_home, output.splitlines())), 1)
self.assertEqual(len(filter(contains_work, out.splitlines())), 1)
self.assertEqual(len(filter(contains_home, out.splitlines())), 1)
def test_context_initially_empty(self):
"""
Test that no context is set initially.
"""
self.t(('context', 'define', 'work', 'project:Work'))
self.t(('context', 'define', 'home', '+home'))
self.t('context define work project:Work')
self.t('context define home +home')
output = self.t(('context', 'show'))[1]
self.assertIn('No context is currently applied.', output)
code, out, err = self.t('context show')
self.assertIn('No context is currently applied.', out)
self.assertFalse(any(re.search("^context=", line) for line in self.t.taskrc_content))
def test_context_setting(self):
@@ -179,11 +174,11 @@ class ContextManagementTest(TestCase):
Test simple context setting.
"""
self.t(('context', 'define', 'work', 'project:Work'))
self.t(('context', 'define', 'home', '+home'))
self.t('context define work project:Work')
self.t('context define home home')
output = self.t(('context', 'home'))[1]
self.assertIn("Context 'home' set.", output)
code, out, err = self.t('context home')
self.assertIn("Context 'home' set.", out)
self.assertIn("context=home\n", self.t.taskrc_content)
def test_context_resetting(self):
@@ -191,12 +186,12 @@ class ContextManagementTest(TestCase):
Test resetting the same context.
"""
self.t(('context', 'define', 'work', 'project:Work'))
self.t(('context', 'define', 'home', '+home'))
self.t('context define work project:Work')
self.t('context define home +home')
self.t(('context', 'home'))
output = self.t(('context', 'home'))[1]
self.assertIn("Context 'home' set.", output)
self.t('context home')
code, out, err = self.t('context home')
self.assertIn("Context 'home' set.", out)
contains_home = lambda line: line == "context=home\n"
self.assertEqual(len(filter(contains_home, self.t.taskrc_content)), 1)
@@ -206,28 +201,28 @@ class ContextManagementTest(TestCase):
Test changing the context.
"""
self.t(('context', 'define', 'work', 'project:Work'))
self.t(('context', 'define', 'home', '+home'))
self.t('context define work project:Work')
self.t('context define home +home')
contains_home = lambda line: line == "context=home\n"
contains_work = lambda line: line == "context=work\n"
# Switch to home context
output = self.t(('context', 'home'))[1]
self.assertIn("Context 'home' set.", output)
code, out, err = self.t('context home')
self.assertIn("Context 'home' set.", out)
self.assertEqual(len(filter(contains_home, self.t.taskrc_content)), 1)
# Switch to work context
output = self.t(('context', 'work'))[1]
self.assertIn("Context 'work' set.", output)
code, out, err = self.t('context work')
self.assertIn("Context 'work' set.", out)
self.assertNotIn("context=home\n", self.t.taskrc_content)
self.assertEqual(len(filter(contains_work, self.t.taskrc_content)), 1)
# Switch back to home context
output = self.t(('context', 'home'))[1]
self.assertIn("Context 'home' set.", output)
code, out, err = self.t('context home')
self.assertIn("Context 'home' set.", out)
self.assertNotIn("context=work\n", self.t.taskrc_content)
self.assertEqual(len(filter(contains_home, self.t.taskrc_content)), 1)
@@ -237,103 +232,103 @@ class ContextManagementTest(TestCase):
Test removing the context.
"""
self.t(('context', 'define', 'work', 'project:Work'))
self.t(('context', 'define', 'home', '+home'))
self.t('context define work project:Work')
self.t('context define home +home')
self.t(('context', 'home'))
output = self.t(('context', 'none'))[1]
self.t('context home')
code, out, err = self.t('context none')
# Assert expected output.
self.assertIn("Context unset.", output)
self.assertIn("Context unset.", out)
# Assert no context definition in the taskrc
contains_any_context = lambda line: re.match('^context=', line)
self.assertFalse(any(contains_any_context(line) for line in self.t.taskrc_content))
# Assert no context showing up using show subcommand
output = self.t(('context', 'show'))[1]
self.assertIn("No context is currently applied.", output)
code, out, err = self.t('context show')
self.assertIn("No context is currently applied.", out)
def test_context_unsetting_after_switching(self):
"""
Test unsetting the context after changing the context around.
"""
self.t(('context', 'define', 'work', 'project:Work'))
self.t(('context', 'define', 'home', '+home'))
self.t('context define work project:Work')
self.t('context define home +home')
# Switch to contexts around
self.t(('context', 'home'))
self.t(('context', 'work'))
self.t(('context', 'home'))
self.t('context home')
self.t('context work')
self.t('context home')
# Unset the context
output = self.t(('context', 'none'))[1]
code, out, err = self.t('context none')
# Assert expected output.
self.assertIn("Context unset.", output)
self.assertIn("Context unset.", out)
# Assert no context definition in the taskrc
contains_any_context = lambda line: re.match('^context=', line)
self.assertFalse(any(contains_any_context(line) for line in self.t.taskrc_content))
# Assert no context showing up using show subcommand
output = self.t(('context', 'show'))[1]
self.assertIn("No context is currently applied.", output)
code, out, err = self.t('context show')
self.assertIn("No context is currently applied.", out)
def test_context_unsetting_with_no_context_set(self):
"""
Test removing the context when no context is set.
"""
self.t(('context', 'define', 'work', 'project:Work'))
self.t(('context', 'define', 'home', '+home'))
self.t('context define work project:Work')
self.t('context define home +home')
output = self.t.runError(('context', 'none'))[1]
code, out, err = self.t.runError('context none')
# Assert expected output.
self.assertIn("Context not unset.", output)
self.assertIn("Context not unset.", out)
# Assert no context definition in the taskrc
contains_any_context = lambda line: re.match('^context=', line)
self.assertFalse(any(contains_any_context(line) for line in self.t.taskrc_content))
# Assert no context showing up using show subcommand
output = self.t(('context', 'show'))[1]
self.assertIn("No context is currently applied.", output)
code, out, err = self.t('context show')
self.assertIn("No context is currently applied.", out)
def test_context_completion(self):
def test_context(self):
"""
Test the _context command.
"""
self.t(('context', 'define', 'work', 'project:Work'))
self.t(('context', 'define', 'home', '+home'))
self.t('context define work project:Work')
self.t('context define home +home')
output = self.t(('_context',))[1]
code, out, err = self.t('_context')
# Assert expected output.
self.assertIn("work", output.splitlines())
self.assertIn("home", output.splitlines())
self.assertEqual(len(output.splitlines()), 2)
self.assertIn("work", out.splitlines())
self.assertIn("home", out.splitlines())
self.assertEqual(len(out.splitlines()), 2)
def test_context_completion(self):
"""
Test the _context command with some context set.
"""
self.t(('context', 'define', 'work', 'project:Work'))
self.t(('context', 'define', 'home', '+home'))
self.t('context define work project:Work')
self.t('context define home +home')
# Activete some context
self.t(('context', 'work'))
self.t('context work')
output = self.t(('_context',))[1]
code, out, err = self.t('_context')
# Assert expected output.
self.assertIn("work", output.splitlines())
self.assertIn("home", output.splitlines())
self.assertEqual(len(output.splitlines()), 2)
self.assertIn("work", out.splitlines())
self.assertIn("home", out.splitlines())
self.assertEqual(len(out.splitlines()), 2)
class ContextEvaluationTest(TestCase):
@@ -341,105 +336,105 @@ class ContextEvaluationTest(TestCase):
self.t = Task()
# Setup contexts
self.t(('context', 'define', 'work', 'project:Work'))
self.t(('context', 'define', 'home', '+home'))
self.t(('context', 'define', 'today', 'due:today'))
self.t('context define work project:Work')
self.t('context define home +home')
self.t('context define today due:today')
# Setup tasks
self.t(('add', 'project:Work', "work task"))
self.t(('add', '+home', "home task"))
self.t(('add', 'project:Work', 'due:today', 'work today task'))
self.t(('add', '+home', 'due:today', 'home today task'))
self.t('add project:Work "work task"')
self.t('add +home "home task"')
self.t('add project:Work due:today "work today task"')
self.t('add +home due:today "home today task"')
def test_context_evaluation(self):
"""
Test the context applied with report list command.
"""
output = self.t(('list',))[1]
code, out, err = self.t('list')
# Assert all the tasks are present in the output
self.assertIn("work task", output)
self.assertIn("home task", output)
self.assertIn("work today task", output)
self.assertIn("home today task", output)
self.assertIn("work task", out)
self.assertIn("home task", out)
self.assertIn("work today task", out)
self.assertIn("home today task", out)
# Set the home context and rerun the report
self.t(('context', 'home'))
output = self.t(('list',))[1]
self.t('context home')
code, out, err = self.t('list')
# Assert all the tasks with the home tag are present in the output
self.assertNotIn("work task", output)
self.assertIn("home task", output)
self.assertNotIn("work today task", output)
self.assertIn("home today task", output)
self.assertNotIn("work task", out)
self.assertIn("home task", out)
self.assertNotIn("work today task", out)
self.assertIn("home today task", out)
def test_context_evaluation_switching(self):
"""
Test swtiching context using the list report.
"""
output = self.t(('list',))[1]
code, out, err = self.t('list')
# Assert all the tasks are present in the output
self.assertIn("work task", output)
self.assertIn("home task", output)
self.assertIn("work today task", output)
self.assertIn("home today task", output)
self.assertIn("work task", out)
self.assertIn("home task", out)
self.assertIn("work today task", out)
self.assertIn("home today task", out)
# Set the home context and rerun the report
self.t(('context', 'home'))
output = self.t(('list',))[1]
self.t('context home')
code, out, err = self.t('list')
# Assert all the tasks with the home tag are present in the output
self.assertNotIn("work task", output)
self.assertIn("home task", output)
self.assertNotIn("work today task", output)
self.assertIn("home today task", output)
self.assertNotIn("work task", out)
self.assertIn("home task", out)
self.assertNotIn("work today task", out)
self.assertIn("home today task", out)
# Set the work context and rerun the report
self.t(('context', 'work'))
output = self.t(('list',))[1]
self.t('context work')
code, out, err = self.t('list')
# Assert all the tasks with the home tag are present in the output
self.assertIn("work task", output)
self.assertNotIn("home task", output)
self.assertIn("work today task", output)
self.assertNotIn("home today task", output)
self.assertIn("work task", out)
self.assertNotIn("home task", out)
self.assertIn("work today task", out)
self.assertNotIn("home today task", out)
# Set the today context and rerun the report
self.t(('context', 'today'))
output = self.t(('list',))[1]
self.t('context today')
code, out, err = self.t('list')
# Assert all the tasks with the home tag are present in the output
self.assertNotIn("work task", output)
self.assertNotIn("home task", output)
self.assertIn("work today task", output)
self.assertIn("home today task", output)
self.assertNotIn("work task", out)
self.assertNotIn("home task", out)
self.assertIn("work today task", out)
self.assertIn("home today task", out)
def test_context_evaluation_unset(self):
"""
Test unsetting context with report list command.
"""
self.t(('context', 'home'))
output = self.t(('list',))[1]
self.t('context home')
code, out, err = self.t('list')
# Assert all the tasks home tagged tasks are present
self.assertNotIn("work task", output)
self.assertIn("home task", output)
self.assertNotIn("work today task", output)
self.assertIn("home today task", output)
self.assertNotIn("work task", out)
self.assertIn("home task", out)
self.assertNotIn("work today task", out)
self.assertIn("home today task", out)
# Set the context to none
self.t(('context', 'none'))
output = self.t(('list',))[1]
self.t('context none')
code, out, err = self.t('list')
# Assert all the tasks are present in the output
self.assertIn("work task", output)
self.assertIn("home task", output)
self.assertIn("work today task", output)
self.assertIn("home today task", output)
self.assertIn("work task", out)
self.assertIn("home task", out)
self.assertIn("work today task", out)
self.assertIn("home today task", out)
def test_context_evaluation_with_user_filters(self):
"""
@@ -448,24 +443,24 @@ class ContextEvaluationTest(TestCase):
"""
# Set the home context
self.t(('context', 'home'))
output = self.t(('list', 'due:today'))[1]
self.t('context home')
code, out, err = self.t('list due:today')
# Assert all the tasks are present in the output
self.assertNotIn("work task", output)
self.assertNotIn("home task", output)
self.assertNotIn("work today task", output)
self.assertIn("home today task", output)
self.assertNotIn("work task", out)
self.assertNotIn("home task", out)
self.assertNotIn("work today task", out)
self.assertIn("home today task", out)
# Set the work context and rerun the report
self.t(('context', 'work'))
output = self.t(('list', 'due:today'))[1]
self.t('context work')
code, out, err = self.t('list due:today')
# Assert all the tasks are present in the output
self.assertNotIn("work task", output)
self.assertNotIn("home task", output)
self.assertIn("work today task", output)
self.assertNotIn("home today task", output)
self.assertNotIn("work task", out)
self.assertNotIn("home task", out)
self.assertIn("work today task", out)
self.assertNotIn("home today task", out)
if __name__ == "__main__":

View File

@@ -41,17 +41,17 @@ class TestCount(TestCase):
def setUpClass(cls):
"""Executed once before any test in the class"""
cls.t = Task()
cls.t(("add", "one"))
cls.t(("log", "two"))
cls.t(("add", "three"))
cls.t(("1", "delete"))
cls.t("add one")
cls.t("log two")
cls.t("add three")
cls.t("1 delete")
def test_count_unfiltered(self):
code, out, err = self.t(("count",))
code, out, err = self.t("count")
self.assertEqual(out.strip(), "3")
def test_count_filtered(self):
code, out, err = self.t(("status:deleted", "count"))
code, out, err = self.t("status:deleted count")
self.assertEqual(out.strip(), "1")

View File

@@ -52,7 +52,7 @@ class TestCustomConfig(TestCase):
Reported in bug 1065
"""
code, out, err = self.t(("show", "alias"))
code, out, err = self.t("show alias")
self.assertIn(self.DIFFER_MSG, out)
self.assertNotIn(self.NOT_RECOG_MSG, out)
@@ -62,7 +62,7 @@ class TestCustomConfig(TestCase):
Reported in bug 1065
"""
code, out, err = self.t(("show",))
code, out, err = self.t("show")
self.assertIn(self.DIFFER_MSG, out)
self.assertIn(self.NOT_RECOG_MSG, out)
@@ -72,7 +72,7 @@ class TestCustomConfig(TestCase):
Reported in bug 1065
"""
code, out, err = self.t(("show", "report.overdue"))
code, out, err = self.t("show report.overdue")
self.assertNotIn(self.DIFFER_MSG, out)
self.assertNotIn(self.NOT_RECOG_MSG, out)
@@ -82,7 +82,7 @@ class TestCustomConfig(TestCase):
Reported in bug 1065
"""
code, out, err = self.t(("show", "notrecog"))
code, out, err = self.t("show notrecog")
self.assertNotIn(self.DIFFER_MSG, out)
self.assertIn(self.NOT_RECOG_MSG, out)

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -45,10 +45,10 @@ class BaseDateTimeNegativeTest(TestCase):
self.t = Task()
def assertInvalidDatetimeFormat(self, value):
self.t.runError(('add', 'due:%s' % value, 'test1'))
self.t.runError(('add', 'scheduled:%s' % value, 'test2'))
self.t.runError(('add', 'wait:%s' % value, 'test3'))
self.t.runError(('add', 'until:%s' % value, 'test4'))
self.t.runError('add due:{0} test1'.format(value))
self.t.runError('add scheduled:{0} test2'.format(value))
self.t.runError('add wait:{0} test3'.format(value))
self.t.runError('add until:{0} test4'.format(value))
class TestIncorrectDate(BaseDateTimeNegativeTest):
@@ -390,7 +390,7 @@ class TestIncorrectTime(BaseDateTimeNegativeTest):
# longer considered an offset, and is instead considered to be the addition
# or subtraction of two times. Although valid, the tests are not
# datetime-negative.t tests.
#
#
# Tests were:
# 12:12:12-13:00
# 12:12:12-24:00

View File

@@ -41,17 +41,17 @@ class TestCMD(TestCase):
cls.t = Task()
cls.t.config("default.command", "list")
cls.t(('add', 'one'))
cls.t(('add', 'two'))
cls.t('add one')
cls.t('add two')
def test_default_command(self):
"""default command"""
code, out, err = self.t(())
code, out, err = self.t()
self.assertIn("task list]", err)
def test_info_command(self):
"""info command"""
code, out, err = self.t(('1'))
code, out, err = self.t('1')
self.assertRegexpMatches(out, 'Description\s+one')

View File

@@ -48,21 +48,21 @@ class TestDiagColor(TestCase):
def test_diag_color(self):
"""Task diag detects terminal as color compatible"""
code, out, err = self.t(("diag",))
code, out, err = self.t("diag")
expected = "\x1b[1m"
self.assertNotIn(expected, out)
def test_diag_nocolor(self):
"""Task diag respects rc:color=off and disables color"""
code, out, err = self.t(("rc.color:off", "diag"))
code, out, err = self.t("rc.color:off diag")
expected = "\x1b[1m"
self.assertNotIn(expected, out)
def test_diag_force_color(self):
"""Task diag respects rc:_forcecolor=on and forces color"""
code, out, err = self.t(("rc._forcecolor:on", "diag"))
code, out, err = self.t("rc._forcecolor:on diag")
expected = "\x1b[1m"
self.assertIn(expected, out)

View File

@@ -40,144 +40,144 @@ class TestDOM(TestCase):
def setUpClass(cls):
cls.t = Task()
cls.t.config("dateformat", "YMD")
cls.t(("add", "one", "due:20110901"))
cls.t(("add", "two", "due:1.due"))
cls.t(("add", "three", "due:20110901", "wait:due", "+tag1", "+tag2"))
cls.t(("3", "annotate", "note"))
cls.t("add one due:20110901")
cls.t("add two due:1.due")
cls.t("add three due:20110901 wait:due +tag1 +tag2")
cls.t("3 annotate note")
def test_dom_task_ref(self):
""" DOM reference to other task """
code, out, err = self.t(("_get", "2.due"))
code, out, err = self.t("_get 2.due")
self.assertIn("2011-09-01T00:00:00", out)
def test_dom_cli_ref(self):
""" DOM reference to current command line """
code, out, err = self.t(("_get", "3.wait"))
code, out, err = self.t("_get 3.wait")
self.assertIn("2011-09-01T00:00:00", out)
def test_dom_id_uuid_roundtrip(self):
""" DOM id/uuid roundtrip """
code, out, err = self.t(("_get", "1.uuid"))
code, out, err = self.t("_get 1.uuid")
uuid = out.strip()
code, out, err = self.t(("_get", uuid + ".id"))
code, out, err = self.t("_get {0}.id".format(uuid))
self.assertEqual("1\n", out)
def test_dom_fail(self):
""" DOM lookup of missing item """
code, out, err = self.t(("_get", "4.description"))
code, out, err = self.t("_get 4.description")
self.assertEqual("\n", out)
def test_dom_tags(self):
""" DOM 3.tags """
code, out, err = self.t(("_get", "3.tags"))
code, out, err = self.t("_get 3.tags")
self.assertEqual("tag1,tag2\n", out)
def test_dom_tags_tag1(self):
""" DOM 3.tags.tag1 """
code, out, err = self.t(("_get", "3.tags.tag1"))
code, out, err = self.t("_get 3.tags.tag1")
self.assertEqual("tag1\n", out)
def test_dom_tags_OVERDUE(self):
""" DOM 3.tags.OVERDUE """
code, out, err = self.t(("_get", "3.tags.OVERDUE"))
code, out, err = self.t("_get 3.tags.OVERDUE")
self.assertEqual("OVERDUE\n", out)
def test_dom_due_year(self):
""" DOM 3.due.year """
code, out, err = self.t(("_get", "3.due.year"))
code, out, err = self.t("_get 3.due.year")
self.assertEqual("2011\n", out)
def test_dom_due_month(self):
""" DOM 3.due.month """
code, out, err = self.t(("_get", "3.due.month"))
code, out, err = self.t("_get 3.due.month")
self.assertEqual("9\n", out)
def test_dom_due_day(self):
""" DOM 3.due.day """
code, out, err = self.t(("_get", "3.due.day"))
code, out, err = self.t("_get 3.due.day")
self.assertEqual("1\n", out)
def test_dom_due_week(self):
""" DOM 3.due.week """
code, out, err = self.t(("_get", "3.due.week"))
code, out, err = self.t("_get 3.due.week")
self.assertEqual("36\n", out)
def test_dom_due_weekday(self):
""" DOM 3.due.weekday """
code, out, err = self.t(("_get", "3.due.weekday"))
code, out, err = self.t("_get 3.due.weekday")
self.assertEqual("4\n", out)
def test_dom_due_hour(self):
""" DOM 3.due.hour """
code, out, err = self.t(("_get", "3.due.hour"))
code, out, err = self.t("_get 3.due.hour")
self.assertEqual("0\n", out)
def test_dom_due_minute(self):
""" DOM 3.due.minute """
code, out, err = self.t(("_get", "3.due.minute"))
code, out, err = self.t("_get 3.due.minute")
self.assertEqual("0\n", out)
def test_dom_due_second(self):
""" DOM 3.due.second """
code, out, err = self.t(("_get", "3.due.second"))
code, out, err = self.t("_get 3.due.second")
self.assertEqual("0\n", out)
def test_dom_annotation_entry(self):
""" DOM 3.annotations.1.entry """
code, out, err = self.t(("_get", "3.annotations.1.entry"))
code, out, err = self.t("_get 3.annotations.1.entry")
self.assertRegexpMatches(out, r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}")
def test_dom_annotation_description(self):
""" DOM 3.annotations.1.description """
code, out, err = self.t(("_get", "3.annotations.1.description"))
code, out, err = self.t("_get 3.annotations.1.description")
self.assertIn("note\n", out)
def test_dom_system_version(self):
""" DOM system.version """
code, out, err = self.t(("_get", "system.version"))
code, out, err = self.t("_get system.version")
self.assertEqual(code, 0)
self.assertRegexpMatches(out, r"\d\.\d+\.\d+")
def test_dom_system_os(self):
""" DOM system.os """
code, out, err = self.t(("_get", "system.os"))
code, out, err = self.t("_get system.os")
self.assertEqual(code, 0)
self.assertEqual(len(out) > 4, True)
self.assertNotIn("<unknown>", out)
def test_dom_context_program(self):
""" DOM context.program """
code, out, err = self.t(("_get", "context.program"))
code, out, err = self.t("_get context.program")
self.assertEqual(code, 0)
self.assertIn("task", out)
def test_dom_context_args(self):
""" DOM context.args """
code, out, err = self.t(("_get", "context.args"))
code, out, err = self.t("_get context.args")
self.assertEqual(code, 0)
self.assertIn("task _get context.args", out)
def test_dom_context_width(self):
""" DOM context.width """
code, out, err = self.t(("_get", "context.width"))
code, out, err = self.t("_get context.width")
self.assertEqual(code, 0)
self.assertRegexpMatches(out, r"\d+")
def test_dom_context_height(self):
""" DOM context.height """
code, out, err = self.t(("_get", "context.height"))
code, out, err = self.t("_get context.height")
self.assertEqual(code, 0)
self.assertRegexpMatches(out, r"\d+")
def test_dom_rc_name(self):
""" DOM rc.dateformat """
code, out, err = self.t(("_get", "rc.dateformat"))
code, out, err = self.t("_get rc.dateformat")
self.assertEqual(code, 0)
self.assertIn("YMD", out)
def test_dom_rc_missing(self):
""" DOM rc.missing """
code, out, err = self.t.runError(("_get", "rc.missing"))
code, out, err = self.t.runError("_get rc.missing")
self.assertEqual(code, 1)

View File

@@ -58,12 +58,12 @@ class TestDue(TestCase):
self.just = timestamp_without_leading_zeros(just)
self.almost = timestamp_without_leading_zeros(almost)
self.t(("add", "one", "due:{0}".format(self.just)))
self.t(("add", "two", "due:{0}".format(self.almost)))
self.t("add one due:{0}".format(self.just))
self.t("add two due:{0}".format(self.almost))
def test_due(self):
"""due tasks displayed correctly"""
code, out, err = self.t(("list",))
code, out, err = self.t("list")
self.assertRegexpMatches(out, "\033\[31m.+{0}.+\033\[0m".format(self.just))
self.assertRegexpMatches(out, "\s+{0}\s+".format(self.almost))
@@ -85,17 +85,17 @@ class TestBug418(TestCase):
def test_bug_418(self):
"""due.before:eow bad with dateformat 'MD'"""
self.t(("add", "one", "due:6/28/2010"))
self.t(("add", "two", "due:6/29/2010"))
self.t(("add", "three", "due:6/30/2010"))
self.t(("add", "four", "due:7/1/2010"))
self.t(("add", "five", "due:7/2/2010"))
self.t(("add", "six", "due:7/3/2010"))
self.t(("add", "seven", "due:7/4/2010"))
self.t(("add", "eight", "due:7/5/2010"))
self.t(("add", "nine", "due:7/6/2010"))
self.t("add one due:6/28/2010")
self.t("add two due:6/29/2010")
self.t("add three due:6/30/2010")
self.t("add four due:7/1/2010")
self.t("add five due:7/2/2010")
self.t("add six due:7/3/2010")
self.t("add seven due:7/4/2010")
self.t("add eight due:7/5/2010")
self.t("add nine due:7/6/2010")
code, out, err = self.t(("foo",))
code, out, err = self.t("foo")
self.assertIn("one", out)
self.assertIn("two", out)
self.assertIn("three", out)
@@ -106,7 +106,7 @@ class TestBug418(TestCase):
self.assertIn("eight", out)
self.assertIn("nine", out)
code, out, err = self.t(("foo", "due.before:7/2/2010"))
code, out, err = self.t("foo due.before:7/2/2010")
self.assertIn("one", out)
self.assertIn("two", out)
self.assertIn("three", out)

View File

@@ -48,13 +48,13 @@ class TestTaskEdit(TestCase):
def test_newline_description_edit(self):
"""task edit - parsing entries containing multiline descriptions"""
self.t(("add", "Hello\nLost"))
self.t('add "Hello\nLost"')
code, out, err = self.t()
self.assertIn("Lost", out)
# Newlines may not be correctly parsed
code, out, err = self.t(("1", "edit"))
code, out, err = self.t("1 edit")
code, out, err = self.t()
self.assertIn("Lost", out)
@@ -62,14 +62,14 @@ class TestTaskEdit(TestCase):
def test_newline_annotation_edit(self):
"""task edit - parsing entries containing multiline annotations"""
self.t(("add", "Hello"))
self.t(("1", "annotate", "Something\nLost"))
self.t("add Hello")
self.t('1 annotate "Something\nLost"')
code, out, err = self.t()
self.assertIn("Lost", out)
# Newlines may not be correctly parsed
code, out, err = self.t(("1", "edit"))
code, out, err = self.t("1 edit")
code, out, err = self.t()
self.assertIn("Lost", out)

View File

@@ -42,20 +42,20 @@ class TestUtf8(TestCase):
def test_utf8_tags(self):
"""Correct handling of UTF8 characters"""
self.t(("add", "one", "+osobní"))
self.t("add one +osobní")
code, out, err = self.t(("list", "+osobní"))
code, out, err = self.t("list +osobní")
self.assertIn("one", out)
code, out, err = self.t.runError(("list", "-osobní"))
code, out, err = self.t.runError("list -osobní")
self.assertNotIn("one", out)
self.t(("add", "two", "+föo"))
code, out, err = self.t(("list", "+föo"))
self.t("add two +föo")
code, out, err = self.t("list +föo")
self.assertIn("two", out)
self.assertNotIn("one", out)
code, out, err = self.t(("list", "-föo"))
code, out, err = self.t("list -föo")
self.assertNotIn("two", out)
self.assertIn("one", out)
@@ -66,9 +66,9 @@ class TestUtf8(TestCase):
self.t.config("print.empty.columns", "no")
self.t(("add", "abc", "pro:Bar\u263a"))
self.t(("add", "def", "pro:Foo"))
self.t("add def pro:Foo")
code, out, err = self.t(("ls",))
code, out, err = self.t("ls")
expected = re.compile("\S\s{4}abc", re.MULTILINE)
self.assertRegexpMatches(out, expected)

View File

@@ -47,9 +47,9 @@ class TestEnpassantMultiple(BaseTestEnpassant):
def setUp(self):
super(TestEnpassantMultiple, self).setUp()
self.t(("add", "foo"))
self.t(("add", "foo", "bar"))
self.t(("add", "baz foo baz"))
self.t("add foo")
self.t("add foo bar")
self.t("add baz foo baz")
def validate_info(self, id, desc):
code, out, err = self.t((id, "info"))
@@ -73,7 +73,7 @@ class TestEnpassantMultiple(BaseTestEnpassant):
def test_multiple(self):
"Test enpassant in multiple tasks and with multiple changes at once"
self.t(("1,2,3", "done", "/foo/FOO/", "pri:H", "+tag"), input="all\n")
self.t("1,2,3 done /foo/FOO/ pri:H +tag", input="all\n")
self.validate_info("1", desc="FOO")
self.validate_info("2", desc="FOO bar")
@@ -84,35 +84,35 @@ class TestEnpassant(BaseTestEnpassant):
def setUp(self):
super(TestEnpassant, self).setUp()
self.t(("add", "one"))
self.t(("add", "two"))
self.t(("add", "three"))
self.t(("add", "four"))
self.t(("add", "five"))
self.t("add one")
self.t("add two")
self.t("add three")
self.t("add four")
self.t("add five")
def perform_action(self, action):
self.t(("1", action, "oneanno"))
code, out, err = self.t(("1", "info"))
code, out, err = self.t("1 info")
self.assertRegexpMatches(out, "Description +one\n[0-9: -]+ oneanno",
msg="{0} enpassant annotation".format(action))
self.t(("2", action, "/two/TWO/"))
code, out, err = self.t(("2", "info"))
code, out, err = self.t("2 info")
self.assertRegexpMatches(out, "Description +TWO",
msg="{0} enpassant modify".format(action))
self.t(("3", action, "+threetag"))
code, out, err = self.t(("3", "info"))
code, out, err = self.t("3 info")
self.assertRegexpMatches(out, "Tags +threetag",
msg="{0} enpassant tag".format(action))
self.t(("4", action, "pri:H"))
code, out, err = self.t(("4", "info"))
code, out, err = self.t("4 info")
self.assertRegexpMatches(out, "Priority +H",
msg="{0} enpassant priority".format(action))
self.t(("5", action, "pro:PROJ"))
code, out, err = self.t(("5", "info"))
code, out, err = self.t("5 info")
self.assertRegexpMatches(out, "Project +PROJ",
msg="{0} enpassant project".format(action))
@@ -130,7 +130,7 @@ class TestEnpassant(BaseTestEnpassant):
def test_stop(self):
"""Test 'stop' with en-passant changes"""
self.t(("1-5", "start"), input="all\n")
self.t("1-5 start", input="all\n")
self.perform_action("stop")

View File

@@ -45,10 +45,11 @@ DATETIME_FORMAT = "%Y%m%dT%H%M%SZ"
class TestExportCommand(TestCase):
def setUp(self):
self.t = Task()
self.t(('add', 'test'))
self.t('add test')
def export(self, identifier):
return json.loads(self.t((str(identifier), 'rc.json.array=off', 'export'))[1].strip())
def export(self, id):
code, out, err = self.t(("{0}".format(id), "rc.json.array=off", "export"))
return json.loads(out.strip())
def assertType(self, value, type):
self.assertEqual(isinstance(value, type), True)
@@ -102,48 +103,48 @@ class TestExportCommand(TestCase):
self.assertString(self.export(1)['description'], "test")
def test_export_start(self):
self.t(('1', 'start'))
self.t('1 start')
self.assertTimestamp(self.export(1)['start'])
def test_export_end(self):
self.t(('1', 'start'))
self.t('1 start')
self.t.faketime("+5s")
# After a task is "done" or "deleted", it does not have an ID by which
# to filter it anymore. Add a tag to work around this.
self.t(('1', 'done', '+workaround'))
self.t('1 done +workaround')
self.assertTimestamp(self.export('+workaround')['end'])
def test_export_due(self):
self.t(('1', 'modify', 'due:today'))
self.t('1 modify due:today')
self.assertTimestamp(self.export(1)['due'])
def test_export_wait(self):
self.t(('1', 'modify', 'wait:tomorrow'))
self.t('1 modify wait:tomorrow')
self.assertTimestamp(self.export(1)['wait'])
def test_export_modified(self):
self.assertTimestamp(self.export(1)['modified'])
def test_export_scheduled(self):
self.t(('1', 'modify', 'schedule:tomorrow'))
self.t('1 modify schedule:tomorrow')
self.assertTimestamp(self.export(1)['scheduled'])
def test_export_recur(self):
self.t(('1', 'modify', 'recur:daily', 'due:today'))
self.t('1 modify recur:daily due:today')
self.assertString(self.export(1)['recur'], "daily")
def test_export_project(self):
self.t(('1', 'modify', 'project:Home'))
self.t('1 modify project:Home')
self.assertString(self.export(1)['project'], "Home")
def test_export_priority(self):
self.t(('1', 'modify', 'priority:H'))
self.t('1 modify priority:H')
self.assertString(self.export(1)['priority'], "H")
def test_export_depends(self):
self.t(('add', 'everything depends on me task'))
self.t(('add', 'wrong, everything depends on me task'))
self.t(('1', 'modify', 'depends:2,3'))
self.t('1 modify depends:2,3')
values = self.export(1)['depends']
self.assertString(values)
@@ -152,29 +153,29 @@ class TestExportCommand(TestCase):
self.assertString(uuid, UUID_REGEXP, regexp=True)
def test_export_urgency(self):
self.t(('add', 'urgent task', '+urgent'))
self.t('add urgent task +urgent')
# Urgency can be either integer or float
self.assertNumeric(self.export(1)['urgency'])
def test_export_numeric_uda(self):
self.t.config('uda.estimate.type', 'numeric')
self.t(('add', 'estimate:42', 'test numeric uda'))
self.t('add estimate:42 test numeric uda')
self.assertNumeric(self.export('2')['estimate'], 42)
def test_export_string_uda(self):
self.t.config('uda.estimate.type', 'string')
self.t(('add', 'estimate:big', 'test string uda'))
self.t('add estimate:big test string uda')
self.assertString(self.export('2')['estimate'], 'big')
def test_export_datetime_uda(self):
self.t.config('uda.estimate.type', 'date')
self.t(('add', 'estimate:eom', 'test date uda'))
self.t('add estimate:eom test date uda')
self.assertTimestamp(self.export('2')['estimate'])
def test_export_duration_uda(self):
self.t.config('uda.estimate.type', 'duration')
self.t(('add', 'estimate:month', 'test duration uda'))
self.t('add estimate:month test duration uda')
self.assertString(self.export('2')['estimate'], 'month')
if __name__ == "__main__":

View File

@@ -50,16 +50,16 @@ class TestDefaultProject(TestCase):
"""
self.set_default_project()
self.t(("add", "foobar", "project:garden"))
code, out, err = self.t("1", "info")
self.t("add foobar project:garden")
code, out, err = self.t("1 info")
self.assertIn("foobar", out)
expected = "Project\s+garden"
self.assertRegexpMatches(out, expected)
self.t(("1", "modify", "project:"))
code, out, err = self.t("1", "info")
self.t("1 modify project:")
code, out, err = self.t("1 info")
self.assertIn("foobar", out)
self.assertNotRegexpMatches(out, expected)
@@ -71,8 +71,8 @@ class TestDefaultProject(TestCase):
"""default.project applied when no project is specified"""
self.set_default_project()
self.t(("add", "foobar"))
code, out, err = self.t("1", "info")
self.t("add foobar")
code, out, err = self.t("1 info")
self.assertIn("foobar", out)
@@ -83,7 +83,7 @@ class TestDefaultProject(TestCase):
"""no project applied when default.project is overridden"""
self.set_default_project()
self.t(("add", "foobar", "rc.default.project="))
self.t("add foobar rc.default.project=")
code, out, err = self.t("1", "info")
self.assertIn("foobar", out)
@@ -91,38 +91,38 @@ class TestDefaultProject(TestCase):
def test_without_default_project(self):
"""no project applied when default.project is blank"""
self.t(("add", "foobar"))
code, out, err = self.t("1", "info")
self.t("add foobar")
code, out, err = self.t("1 info")
self.assertIn("foobar", out)
self.assertNotIn("Project", out)
def test_modify_default_project(self):
"""default.project is not applied when modifying a task"""
self.t(("add", "foobar"))
code, out, err = self.t("1", "info")
self.t("add foobar")
code, out, err = self.t("1 info")
self.assertIn("foobar", out)
self.assertNotIn("Project", out)
self.set_default_project()
self.t(("1", "modify", "+tag"))
self.t("1 modify +tag")
code, out, err = self.t("1", "info")
self.assertNotIn("Project", out)
def test_annotate_default_project(self):
"""default.project is not applied when annotating a task"""
self.t(("add", "foobar"))
code, out, err = self.t("1", "info")
self.t("add foobar")
code, out, err = self.t("1 info")
self.assertIn("foobar", out)
self.assertNotIn("Project", out)
self.set_default_project()
self.t(("1", "annotate", "Hello"))
code, out, err = self.t("1", "info")
self.t("1 annotate Hello")
code, out, err = self.t("1 info")
expected = "Description\s+foobar\n[0-9-: ]+ Hello"
self.assertRegexpMatches(out, expected)
@@ -133,16 +133,16 @@ class TestDefaultProject(TestCase):
# Allow keeping track of time spent on task
self.t.config("journal.time", "yes")
self.t(("add", "foobar"))
code, out, err = self.t("1", "info")
self.t("add foobar")
code, out, err = self.t("1 info")
self.assertIn("foobar", out)
self.assertNotIn("Project", out)
self.set_default_project()
self.t(("1", "start"))
self.t(("1", "stop"))
self.t("1 start")
self.t("1 stop")
code, out, err = self.t("1", "info")
self.assertIn("foobar", out)
@@ -153,9 +153,9 @@ class TestDefaultProject(TestCase):
self.set_default_project()
DESC = "foobar"
self.t(("add", "recur:daily", "due:today", DESC))
self.t(('add', 'recur:daily', 'due:today', DESC))
self.t() # Ensure creation of recurring children
code, out, err = self.t(("1", "info"))
code, out, err = self.t("1 info")
self.assertIn(DESC, out)
self.assertRegexpMatches(out, "Status\s+Recurring") # is a parent task
@@ -165,7 +165,7 @@ class TestDefaultProject(TestCase):
self.t() # Ensure creation of recurring children
# Try to figure out the ID of last created task
code, out, err = self.t(("count",))
code, out, err = self.t("count")
# Will fail if some other message is printed as part of "count"
id = out.split()[-1]
@@ -189,7 +189,7 @@ class TestDefaultProject(TestCase):
"""no project is applied on recurring tasks"""
# NOTE - reported on TW-1279
DESC = "foobar"
self.t(("add", "recur:daily", "due:today", DESC))
self.t(('add', 'recur:daily', 'due:today', DESC))
code, out, err = self.t()
self.assertIn(DESC, out)
@@ -211,7 +211,7 @@ class TestDefaultProject(TestCase):
self.set_default_project()
DESC = "foobar"
self.t(("add", "recur:daily", "due:today", "project:HELLO", DESC))
self.t(('add', 'recur:daily', 'due:today', 'project:HELLO', DESC))
code, out, err = self.t()
self.assertIn(DESC, out)
@@ -243,7 +243,7 @@ class ServerTestDefaultProject(ServerTestCase):
# NOTE - reported on TW-1287
desc = "Testing task"
self.t1(("add", desc))
self.t1(("sync",))
self.t1("sync")
code, out, err = self.t1()
@@ -252,18 +252,18 @@ class ServerTestDefaultProject(ServerTestCase):
# Testing scenario - default.project is applied on task arrival
proj2 = "Client2"
self.t2.config("default.project", proj2)
self.t2(("sync",))
self.t2("sync")
code, out, err = self.t2()
self.assertIn(desc, out)
self.assertNotIn(proj2, out)
self.t2(("sync",))
self.t2("sync")
# Testing scenario - default.project is applied on task delivery
proj3 = "Client3"
self.t3.config("default.project", proj3)
self.t3(("sync",))
self.t3("sync")
code, out, err = self.t3()
self.assertIn(desc, out)

View File

@@ -42,13 +42,13 @@ class TestRecurrenceProblems(TestCase):
"""Removing due from a recurring task causes date wrapping"""
# Originally bug.327.t
self.t(("add", "foo", "recur:yearly", "due:eoy"))
self.t(("list",)) # Trigger garbage collection
self.t("add foo recur:yearly due:eoy")
self.t("list") # Trigger garbage collection
code, out, err = self.t.runError(("2", "modify", "due:"))
code, out, err = self.t.runError("2 modify due:")
self.assertIn("cannot remove the due date from a recurring task", err)
code, out, err = self.t(("list",))
code, out, err = self.t("list")
self.assertIn("\n1 task", out)
self.assertNotIn("1969", out)
@@ -59,8 +59,8 @@ class TestRecurrenceProblems(TestCase):
self.t.config("dateformat.info", "m/d/Y")
self.t(("add", "foo", "due:today", "recur:yearly", "until:eom"))
code, out, err = self.t(("info", "1"))
self.t("add foo due:today recur:yearly until:eom")
code, out, err = self.t("info 1")
self.assertNotRegexpMatches(out, "Until\s+\d{10}")
self.assertRegexpMatches(out, "Until\s+\d+\/\d+\/\d{4}")

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -33,6 +33,7 @@ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from basetest import Task, TestCase
class TestEmptyFilter(TestCase):
def setUp(self):
self.t = Task()
@@ -40,19 +41,19 @@ class TestEmptyFilter(TestCase):
def test_empty_filter_warning(self):
"""Modify tasks with no filter."""
self.t(("add", "foo"))
self.t(("add", "bar"))
self.t("add foo")
self.t("add bar")
code, out, err = self.t.runError(("modify", "rc.allow.empty.filter=yes", "rc.confirmation=no", "priority:H"))
code, out, err = self.t.runError("modify rc.allow.empty.filter=yes rc.confirmation=no priority:H")
self.assertIn("Command prevented from running.", err)
def test_empty_filter_error(self):
"""Modify tasks with no filter, and disallowed confirmation."""
self.t(("add", "foo"))
self.t(("add", "bar"))
self.t("add foo")
self.t("add bar")
code, out, err = self.t.runError(("modify", "rc.allow.empty.filter=no", "priority:H"))
code, out, err = self.t.runError("modify rc.allow.empty.filter=no priority:H")
self.assertIn("You did not specify a filter, and with the 'allow.empty.filter' value, no action is taken.", err)
if __name__ == "__main__":

View File

@@ -42,18 +42,18 @@ class TestFilterPrefix(TestCase):
cls.t = Task()
cls.t.config("verbose", "nothing")
cls.t(('add', 'project:foo.uno', 'priority:H', '+tag', 'one foo' ))
cls.t(('add', 'project:foo.dos', 'priority:H', 'two' ))
cls.t(('add', 'project:foo.tres', 'three' ))
cls.t(('add', 'project:bar.uno', 'priority:H', 'four' ))
cls.t(('add', 'project:bar.dos', '+tag', 'five' ))
cls.t(('add', 'project:bar.tres', 'six foo' ))
cls.t(('add', 'project:bazuno', 'seven bar foo'))
cls.t(('add', 'project:bazdos', 'eight bar foo'))
cls.t('add project:foo.uno priority:H +tag "one foo"' )
cls.t('add project:foo.dos priority:H "two"' )
cls.t('add project:foo.tres "three"' )
cls.t('add project:bar.uno priority:H "four"' )
cls.t('add project:bar.dos +tag "five"' )
cls.t('add project:bar.tres "six foo"' )
cls.t('add project:bazuno "seven bar foo"')
cls.t('add project:bazdos "eight bar foo"')
def test_list_all(self):
"""No filter shows all tasks."""
code, out, err = self.t(('list',))
code, out, err = self.t('list')
self.assertIn('one', out)
self.assertIn('two', out)
self.assertIn('three', out)
@@ -65,7 +65,7 @@ class TestFilterPrefix(TestCase):
def test_list_project_foo(self):
"""Filter on project name."""
code, out, err = self.t(('list', 'project:foo'))
code, out, err = self.t('list project:foo')
self.assertIn('one', out)
self.assertIn('two', out)
self.assertIn('three', out)
@@ -77,7 +77,7 @@ class TestFilterPrefix(TestCase):
def test_list_project_not_foo(self):
"""Filter on not project name."""
code, out, err = self.t(('list', 'project.not:foo'))
code, out, err = self.t('list project.not:foo')
self.assertIn('one', out)
self.assertIn('two', out)
self.assertIn('three', out)
@@ -89,7 +89,7 @@ class TestFilterPrefix(TestCase):
def test_list_project_startswith_bar(self):
"""Filter on project name start."""
code, out, err = self.t(('list', 'project.startswith:bar'))
code, out, err = self.t('list project.startswith:bar')
self.assertNotIn('one', out)
self.assertNotIn('two', out)
self.assertNotIn('three', out)
@@ -101,7 +101,7 @@ class TestFilterPrefix(TestCase):
def test_list_project_ba(self):
"""Filter on project partial match."""
code, out, err = self.t(('list', 'project:ba'))
code, out, err = self.t('list project:ba')
self.assertNotIn('one', out)
self.assertNotIn('two', out)
self.assertNotIn('three', out)
@@ -113,7 +113,7 @@ class TestFilterPrefix(TestCase):
def test_list_description_has_foo(self):
"""Filter on description pattern."""
code, out, err = self.t(('list', 'description.has:foo'))
code, out, err = self.t('list description.has:foo')
self.assertIn('one', out)
self.assertNotIn('two', out)
self.assertNotIn('three', out)

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -46,7 +46,7 @@ class TestHooksOnLaunch(TestCase):
hookname = 'on-launch-good-env'
self.t.hooks.add_default(hookname, log=True)
code, out, err = self.t(("version", )) # Arbitrary command that generates output.
code, out, err = self.t("version") # Arbitrary command that generates output.
hook = self.t.hooks[hookname]
hook.assertTriggeredCount(1)

View File

@@ -46,7 +46,7 @@ class TestHooksOnAdd(TestCase):
hookname = 'on-add-accept'
self.t.hooks.add_default(hookname, log=True)
code, out, err = self.t(("add", "foo"))
code, out, err = self.t("add foo")
hook = self.t.hooks[hookname]
hook.assertTriggeredCount(1)
@@ -55,7 +55,7 @@ class TestHooksOnAdd(TestCase):
logs = hook.get_logs()
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
code, out, err = self.t(("1", "info"))
code, out, err = self.t("1 info")
self.assertIn("Description foo", out)
def test_onadd_builtin_reject(self):
@@ -63,7 +63,7 @@ class TestHooksOnAdd(TestCase):
hookname = 'on-add-reject'
self.t.hooks.add_default(hookname, log=True)
code, out, err = self.t.runError(("add", "foo"))
code, out, err = self.t.runError("add foo")
hook = self.t.hooks[hookname]
hook.assertTriggeredCount(1)
@@ -77,7 +77,7 @@ class TestHooksOnAdd(TestCase):
hookname = 'on-add-misbehave1'
self.t.hooks.add_default(hookname, log=True)
code, out, err = self.t.runError(("add", "foo"))
code, out, err = self.t.runError("add foo")
hook = self.t.hooks[hookname]
hook.assertTriggeredCount(1)
@@ -91,7 +91,7 @@ class TestHooksOnAdd(TestCase):
hookname = 'on-add-misbehave2'
self.t.hooks.add_default(hookname, log=True)
code, out, err = self.t.runError(("add", "foo"))
code, out, err = self.t.runError("add foo")
self.assertIn("Hook Error: Expected 1 JSON task(s), found 0", err)
hook = self.t.hooks[hookname]
@@ -103,7 +103,7 @@ class TestHooksOnAdd(TestCase):
hookname = 'on-add-misbehave3'
self.t.hooks.add_default(hookname, log=True)
code, out, err = self.t.runError(("add", "foo"))
code, out, err = self.t.runError("add foo")
self.assertIn("Hook Error: Expected 1 JSON task(s), found 2", err)
hook = self.t.hooks[hookname]
@@ -115,7 +115,7 @@ class TestHooksOnAdd(TestCase):
hookname = 'on-add-misbehave4'
self.t.hooks.add_default(hookname, log=True)
code, out, err = self.t.runError(("add", "foo"))
code, out, err = self.t.runError("add foo")
self.assertIn("Hook Error: JSON must be for the same task:", err)
hook = self.t.hooks[hookname]
@@ -130,7 +130,7 @@ class TestHooksOnAdd(TestCase):
hookname = 'on-add-misbehave5'
self.t.hooks.add_default(hookname, log=True)
code, out, err = self.t.runError(("add", "foo"))
code, out, err = self.t.runError("add foo")
self.assertIn("Hook Error: JSON syntax error in: {\"}", err)
hook = self.t.hooks[hookname]
@@ -146,7 +146,7 @@ class TestHooksOnAdd(TestCase):
hookname = 'on-add-misbehave6'
self.t.hooks.add_default(hookname, log=True)
code, out, err = self.t.runError(("add", "foo"))
code, out, err = self.t.runError("add foo")
self.assertIn("Hook Error: JSON Object missing 'uuid' attribute.", err)
hook = self.t.hooks[hookname]

View File

@@ -46,7 +46,7 @@ class TestHooksOnExit(TestCase):
hookname = 'on-exit-good'
self.t.hooks.add_default(hookname, log=True)
code, out, err = self.t(("version",))
code, out, err = self.t("version")
self.assertIn("Taskwarrior", out)
hook = self.t.hooks[hookname]
@@ -62,7 +62,7 @@ class TestHooksOnExit(TestCase):
self.t.hooks.add_default(hookname, log=True)
# Failing hook should prevent processing.
code, out, err = self.t.runError(("version",))
code, out, err = self.t.runError("version")
self.assertIn("Taskwarrior", out)
hook = self.t.hooks[hookname]
@@ -78,7 +78,7 @@ class TestHooksOnExit(TestCase):
self.t.hooks.add_default(hookname, log=True)
# Failing hook should prevent processing.
code, out, err = self.t(("version",))
code, out, err = self.t("version")
self.assertIn("Taskwarrior", out)
hook = self.t.hooks[hookname]
@@ -94,7 +94,7 @@ class TestHooksOnExit(TestCase):
self.t.hooks.add_default(hookname, log=True)
# Failing hook should prevent processing.
code, out, err = self.t.runError(("version",))
code, out, err = self.t.runError("version")
self.assertIn("Hook Error: Expected 0 JSON task(s), found 1", err)
hook = self.t.hooks[hookname]

View File

@@ -46,7 +46,7 @@ class TestHooksOnLaunch(TestCase):
hookname = 'on-launch-good'
self.t.hooks.add_default(hookname, log=True)
code, out, err = self.t(("version",))
code, out, err = self.t("version")
self.assertIn("Taskwarrior", out)
hook = self.t.hooks[hookname]
@@ -62,7 +62,7 @@ class TestHooksOnLaunch(TestCase):
self.t.hooks.add_default(hookname, log=True)
# Failing hook should prevent processing.
code, out, err = self.t.runError(("version",))
code, out, err = self.t.runError("version")
self.assertNotIn("Taskwarrior", out)
hook = self.t.hooks[hookname]
@@ -78,7 +78,7 @@ class TestHooksOnLaunch(TestCase):
self.t.hooks.add_default(hookname, log=True)
# Failing hook should prevent processing.
code, out, err = self.t.runError(("version",))
code, out, err = self.t.runError("version")
self.assertNotIn("Could not get Hook exit status!", err)
hook = self.t.hooks[hookname]
@@ -94,7 +94,7 @@ class TestHooksOnLaunch(TestCase):
self.t.hooks.add_default(hookname, log=True)
# Failing hook should prevent processing.
code, out, err = self.t.runError(("version",))
code, out, err = self.t.runError("version")
self.assertIn("Hook Error: Expected 0 JSON task(s), found 1", err)
hook = self.t.hooks[hookname]

View File

@@ -46,8 +46,8 @@ class TestHooksOnModify(TestCase):
hookname = 'on-modify-accept'
self.t.hooks.add_default(hookname, log=True)
code, out, err = self.t(("add", "foo"))
code, out, err = self.t(("1", "modify", "+tag"))
code, out, err = self.t("add foo")
code, out, err = self.t("1 modify +tag")
hook = self.t.hooks[hookname]
hook.assertTriggeredCount(1)
@@ -56,7 +56,7 @@ class TestHooksOnModify(TestCase):
logs = hook.get_logs()
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
code, out, err = self.t(("1", "info"))
code, out, err = self.t("1 info")
self.assertIn("Description foo", out)
self.assertIn("Tags tag", out)
@@ -65,8 +65,8 @@ class TestHooksOnModify(TestCase):
hookname = 'on-modify-reject'
self.t.hooks.add_default(hookname, log=True)
code, out, err = self.t(("add", "foo"))
code, out, err = self.t.runError(("1", "modify", "+tag"))
code, out, err = self.t("add foo")
code, out, err = self.t.runError("1 modify +tag")
hook = self.t.hooks[hookname]
hook.assertTriggeredCount(1)
@@ -80,8 +80,8 @@ class TestHooksOnModify(TestCase):
hookname = 'on-modify-misbehave2'
self.t.hooks.add_default(hookname, log=True)
code, out, err = self.t(("add", "foo"))
code, out, err = self.t.runError(("1", "modify", "+tag"))
code, out, err = self.t("add foo")
code, out, err = self.t.runError("1 modify +tag")
self.assertIn("Hook Error: Expected 1 JSON task(s), found 0", err)
hook = self.t.hooks[hookname]
@@ -96,8 +96,8 @@ class TestHooksOnModify(TestCase):
hookname = 'on-modify-misbehave3'
self.t.hooks.add_default(hookname, log=True)
code, out, err = self.t(("add", "foo"))
code, out, err = self.t.runError(("1", "modify", "+tag"))
code, out, err = self.t("add foo")
code, out, err = self.t.runError("1 modify +tag")
self.assertIn("Hook Error: Expected 1 JSON task(s), found 2", err)
hook = self.t.hooks[hookname]
@@ -112,8 +112,8 @@ class TestHooksOnModify(TestCase):
hookname = 'on-modify-misbehave4'
self.t.hooks.add_default(hookname, log=True)
code, out, err = self.t(("add", "foo"))
code, out, err = self.t.runError(("1", "modify", "+tag"))
code, out, err = self.t("add foo")
code, out, err = self.t.runError("1 modify +tag")
self.assertIn("Hook Error: JSON must be for the same task:", err)
hook = self.t.hooks[hookname]
@@ -128,8 +128,8 @@ class TestHooksOnModify(TestCase):
hookname = 'on-modify-misbehave5'
self.t.hooks.add_default(hookname, log=True)
code, out, err = self.t(("add", "foo"))
code, out, err = self.t.runError(("1", "modify", "+tag"))
code, out, err = self.t("add foo")
code, out, err = self.t.runError("1 modify +tag")
self.assertIn("Hook Error: JSON syntax error in: {\"}", err)
hook = self.t.hooks[hookname]
@@ -144,8 +144,8 @@ class TestHooksOnModify(TestCase):
hookname = 'on-modify-misbehave6'
self.t.hooks.add_default(hookname, log=True)
code, out, err = self.t(("add", "foo"))
code, out, err = self.t.runError(("1", "modify", "+tag"))
code, out, err = self.t("add foo")
code, out, err = self.t.runError("1 modify +tag")
self.assertIn("Hook Error: JSON Object missing 'uuid' attribute.", err)
hook = self.t.hooks[hookname]

View File

@@ -41,50 +41,50 @@ class TestIDs(TestCase):
def setUpClass(self):
self.t = Task()
self.t(("add", "one", "+A", "+B"))
self.t(("add", "two", "+A" ))
self.t(("add", "three", "+A", "+B"))
self.t(("add", "four" ))
self.t(("add", "five", "+A", "+B"))
self.t("add one +A +B")
self.t("add two +A" )
self.t("add three +A +B")
self.t("add four" )
self.t("add five +A +B")
def test_ids_count_A(self):
"""ids +A"""
code, out, err = self.t(("ids", "+A"))
code, out, err = self.t("ids +A")
self.assertRegexpMatches(out, "^1-3,5$")
def test_ids_count_B(self):
"""ids +B"""
code, out, err = self.t(("ids", "+B"))
code, out, err = self.t("ids +B")
self.assertRegexpMatches(out, "^1,3,5$")
def test_ids_count_A_B(self):
"""ids +A -B"""
code, out, err = self.t(("ids", "+A", "-B"))
code, out, err = self.t("ids +A -B")
self.assertRegexpMatches(out, "^2$")
def test_get_ids_count_A(self):
"""_ids +A"""
code, out, err = self.t(("_ids", "+A"))
code, out, err = self.t("_ids +A")
self.assertRegexpMatches(out, "^1\n2\n3\n5$")
def test_get_zshids_count_A(self):
"""_zshids +A"""
code, out, err = self.t(("_zshids", "+A"))
code, out, err = self.t("_zshids +A")
self.assertRegexpMatches(out, "^1:one\n2:two\n3:three\n5:five$")
def test_uuids_count_A(self):
"""uuids +A"""
code, out, err = self.t(("uuids", "+A"))
code, out, err = self.t("uuids +A")
self.assertRegexpMatches(out, "{0},{0},{0},{0}".format(UUID_REGEXP))
def test_get_uuids_count_A(self):
"""_uuids +A"""
code, out, err = self.t(("_uuids", "+A"))
code, out, err = self.t("_uuids +A")
self.assertRegexpMatches(out, "{0}\n{0}\n{0}\n{0}".format(UUID_REGEXP))
def test_get_zshuuids_count_A(self):
"""_zshuuids +A"""
code, out, err = self.t(("_zshuuids", "+A"))
code, out, err = self.t("_zshuuids +A")
self.assertRegexpMatches(
out, "{0}:one\n{0}:two\n{0}:three\n{0}:five".format(UUID_REGEXP))

View File

@@ -43,9 +43,9 @@ class TestImport(TestCase):
self.t.config("dateformat", "m/d/Y")
self.data1 = """[
{"uuid":"00000000-0000-0000-0000-000000000000","description":"zero","project":"A","status":"pending","entry":"1234567889"},
{"uuid":"11111111-1111-1111-1111-111111111111","description":"one","project":"B","status":"pending","entry":"1234567889"},
{"uuid":"22222222-2222-2222-2222-222222222222","description":"two","status":"completed","entry":"1234524689","end":"1234524690"}
{"uuid":"a0000000-a000-a000-a000-a00000000000","description":"zero","project":"A","status":"pending","entry":"1234567889"},
{"uuid":"a1111111-a111-a111-a111-a11111111111","description":"one","project":"B","status":"pending","entry":"1234567889"},
{"uuid":"a2222222-a222-a222-a222-a22222222222","description":"two","status":"completed","entry":"1234524689","end":"1234524690"}
]
"""
@@ -53,24 +53,24 @@ class TestImport(TestCase):
"""
def assertData1(self):
code, out, err = self.t(("list",))
code, out, err = self.t("list")
self.assertRegexpMatches(out, "1.+A.+zero")
self.assertRegexpMatches(out, "2.+B.+one")
self.assertNotIn("two", out)
code, out, err = self.t(("completed",))
code, out, err = self.t("completed")
self.assertNotIn("zero", out)
self.assertNotIn("one", out)
# complete has completion date as 1st column
self.assertRegexpMatches(out, "2/13/2009.+two")
def assertData2(self):
code, out, err = self.t(("list",))
code, out, err = self.t("list")
self.assertRegexpMatches(out, "3.+three")
def test_import_stdin(self):
"""Import from stdin"""
code, out, err = self.t(("import", "-"), input=self.data1)
code, out, err = self.t("import -", input=self.data1)
self.assertIn("Imported 3 tasks", err)
self.assertData1()
@@ -86,17 +86,17 @@ class TestImport(TestCase):
"""Import from a file"""
filename = mkstemp(self.data1)
code, out, err = self.t(("import", filename))
code, out, err = self.t("import {0}".format(filename))
self.assertIn("Imported 3 tasks", err)
self.assertData1()
def test_double_import(self):
"""Multiple imports persist data"""
code, out, err = self.t(("import", "-"), input=self.data1)
code, out, err = self.t("import -", input=self.data1)
self.assertIn("Imported 3 tasks", err)
code, out, err = self.t(("import", "-"), input=self.data2)
code, out, err = self.t("import -", input=self.data2)
self.assertIn("Imported 1 tasks", err)
self.assertData1()
@@ -105,9 +105,7 @@ class TestImport(TestCase):
def test_import_update(self):
"""Update existing tasks"""
self.t("import", input=self.data1)
self.t("2 delete") # Depends on import order. Bad. See next line.
# TODO: Use this once filtering by UUID works again...
#self.t("11111111-1111-1111-1111-111111111111 delete")
self.t("a1111111-a111-a111-a111-a11111111111 delete")
self.t("next") # Run GC
_t = sorted(self.t.export(), key=lambda t: t["uuid"])
@@ -146,14 +144,53 @@ class TestImport(TestCase):
def test_import_newlines_whitespace(self):
"""JSON array with whitespace before and after names and values"""
_data = """[
{ "uuid":"00000000-0000-0000-0000-000000000000" , "description" : "zero" ,"project":"A", "status":"pending","entry":"1234567889" } ,
{ "uuid":"11111111-1111-1111-1111-111111111111","description":"one","project":"B","status":"pending","entry":"1234567889"}, {"uuid":"22222222-2222-2222-2222-222222222222","description":"two","status":"completed","entry":"1234524689","end":"1234524690" }
{ "uuid":"a0000000-a000-a000-a000-a00000000000" , "description" : "zero" ,"project":"A", "status":"pending","entry":"1234567889" } ,
{ "uuid":"a1111111-a111-a111-a111-a11111111111","description":"one","project":"B","status":"pending","entry":"1234567889"}, {"uuid":"a2222222-a222-a222-a222-a22222222222","description":"two","status":"completed","entry":"1234524689","end":"1234524690" }
]"""
code, out, err = self.t("import", input=_data)
self.assertIn("Imported 3 tasks", err)
self.assertData1()
class TestImportExportRoundtrip(TestCase):
def setUp(self):
self.t1 = Task()
self.t2 = Task()
for client in (self.t1, self.t2):
client.config("dateformat", "m/d/Y")
client.config("verbose", "off")
client.config("defaultwidth", "100")
client.config("json.array", "off")
def _validate_data(self, client):
code, out, err = client("_get 1.priority")
self.assertEqual("H\n", out)
code, out, err = client("_get 1.project")
self.assertEqual("A\n", out)
code, out, err = client("_get 1.description")
self.assertEqual("one/1\n", out)
code, out, err = client("_get 2.tags")
self.assertEqual("tag1,tag2\n", out)
code, out, err = client("_get 2.description")
self.assertEqual("two\n", out)
def test_import_export(self):
"""Test importing exported data"""
self.t1("add priority:H project:A -- one/1")
self.t1("add +tag1 +tag2 two")
code, out1, err = self.t1("export")
self.t2("import -", input=out1)
code, out2, err = self.t2("export")
self.assertEqual(out1, out2)
self._validate_data(self.t1)
self._validate_data(self.t2)
if __name__ == "__main__":
from simpletap import TAPTestRunner
unittest.main(testRunner=TAPTestRunner())

View File

@@ -83,7 +83,7 @@ if __name__ == "__main__":
stop = float(timestamp.match(line).group(1))
# Remove expected failures from the skipped tests category
for filename, value in expected.iteritems():
for filename, value in expected.items():
if skipped[filename] == value:
del skipped[filename]
else:

View File

@@ -46,11 +46,11 @@ class TestProjects(TestCase):
"""'task projects' shouldn't consider deleted tasks in summary.
Reported in bug 1044
"""
self.t(("add", "project:A", "1"))
self.t(("add", "project:B", "2"))
self.t(("add", "project:B", "3"))
self.t(("3", "delete"))
code, out, err = self.t(("project:B", "projects"))
self.t("add project:A 1")
self.t("add project:B 2")
self.t("add project:B 3")
self.t("3 delete")
code, out, err = self.t("project:B projects")
expected = "1 project \(1 task\)"
self.assertRegexpMatches(out, expected)
@@ -58,31 +58,31 @@ class TestProjects(TestCase):
def test_project_progress(self):
"""project status/progress is shown and is up-to-date"""
code, out, err = self.t(("add", "one", "pro:foo"))
code, out, err = self.t("add one pro:foo")
self.assertRegexpMatches(err, self.STATUS.format("foo", "0%",
"1 task"))
code, out, err = self.t(("add", "two", "pro:foo"))
code, out, err = self.t("add two pro:foo")
self.assertRegexpMatches(err, self.STATUS.format("foo", "0%",
"2 of 2 tasks"))
code, out, err = self.t(("add", "three", "pro:foo"))
code, out, err = self.t("add three pro:foo")
self.assertRegexpMatches(err, self.STATUS.format("foo", "0%",
"3 of 3 tasks"))
code, out, err = self.t(("add", "four", "pro:foo"))
code, out, err = self.t("add four pro:foo")
self.assertRegexpMatches(err, self.STATUS.format("foo", "0%",
"4 of 4 tasks"))
code, out, err = self.t(("1", "done"))
code, out, err = self.t("1 done")
self.assertRegexpMatches(err, self.STATUS.format("foo", "25%",
"3 of 4 tasks"))
code, out, err = self.t(("2", "delete"))
code, out, err = self.t("2 delete")
self.assertRegexpMatches(err, self.STATUS.format("foo", "33%",
"2 of 3 tasks"))
code, out, err = self.t(("3", "modify", "pro:bar"))
code, out, err = self.t("3 modify pro:bar")
self.assertRegexpMatches(err, self.STATUS.format("foo", "50%",
"1 of 2 tasks"))
self.assertRegexpMatches(err, self.STATUS.format("bar", "0%",
@@ -91,18 +91,18 @@ class TestProjects(TestCase):
def test_project_spaces(self):
"""projects with spaces are handled correctly"""
self.t(("add", "hello", "pro:bob"))
code, out, err = self.t(("1", "mod", 'pro:"foo bar"'))
self.t("add hello pro:bob")
code, out, err = self.t('1 mod pro:"foo bar"')
self.assertRegexpMatches(err, self.STATUS.format("foo bar", "0%",
"1 task"))
def add_tasks(self):
self.t(("add", "testing", "project:existingParent"))
self.t(("add", "testing", "project:existingParent.child"))
self.t(("add", "testing", "project:abstractParent.kid"))
self.t(("add", "testing", "project:.myProject"))
self.t(("add", "testing", "project:myProject"))
self.t(("add", "testing", "project:.myProject."))
self.t("add testing project:existingParent")
self.t("add testing project:existingParent.child")
self.t("add testing project:abstractParent.kid")
self.t("add testing project:.myProject")
self.t("add testing project:myProject")
self.t("add testing project:.myProject.")
def validate_indentation(self, out):
order = (
@@ -137,7 +137,7 @@ class TestProjects(TestCase):
"""
self.add_tasks()
code, out, err = self.t(("projects",))
code, out, err = self.t("projects")
self.validate_indentation(out)
@@ -148,7 +148,7 @@ class TestProjects(TestCase):
"""
self.add_tasks()
code, out, err = self.t(("summary",))
code, out, err = self.t("summary")
self.validate_indentation(out)
@@ -156,19 +156,19 @@ class TestProjects(TestCase):
class TestBug299(TestCase):
def setUp(self):
self.t = Task()
self.t(("add", "project:one", "foo"))
self.t(("add", "project:ones", "faz"))
self.t(("add", "project:phone", "boo"))
self.t(("add", "project:bones", "too"))
self.t(("add", "project:two", "bar"))
self.t(("add", "project:three", "baz"))
self.t("add project:one foo")
self.t("add project:ones faz")
self.t("add project:phone boo")
self.t("add project:bones too")
self.t("add project:two bar")
self.t("add project:three baz")
def test_project_exclusion_isnt(self):
"""check project exclusion using project.isnt:<name>
Reported in bug 299
"""
code, out, err = self.t(("list", "project.isnt:one", "pro.isnt:two"))
code, out, err = self.t("list project.isnt:one pro.isnt:two")
self.assertNotRegexpMatches(out, "one.*foo")
self.assertRegexpMatches(out, "ones.*faz")
@@ -183,7 +183,7 @@ class TestBug299(TestCase):
Reported in bug 299
"""
code, out, err = self.t(("list", "project.hasnt:one", "pro.hasnt:two"))
code, out, err = self.t("list project.hasnt:one pro.hasnt:two")
self.assertNotRegexpMatches(out, "one.*foo")
self.assertNotRegexpMatches(out, "ones.*faz")
@@ -203,7 +203,7 @@ class TestBug555(TestCase):
Reported in bug 555
"""
code, out, err = self.t(("log", "description", "project:p"))
code, out, err = self.t("log description project:p")
self.assertNotIn("Segmentation fault", out)
self.assertNotIn("Segmentation fault", err)
@@ -221,11 +221,11 @@ class TestBug605(TestCase):
"""
self.t("add One project:p1")
code, out, err = self.t(("1", "delete"), input="y\n")
code, out, err = self.t("1 delete", input="y\n")
self.assertIn("is 0% complete", err)
self.t("add Two project:p1")
code, out, err = self.t(("2", "done"))
code, out, err = self.t("2 done")
self.assertIn("is 100% complete", err)
class TestBug906(TestCase):

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -47,13 +47,13 @@ class TestRecurrenceDisabled(TestCase):
"""
self.t.config("recurrence", "no")
self.t(("add", "due:today", "recur:daily", "Recurrent task."))
self.t("add due:today recur:daily Recurrent task.")
# Trigger GC, expect no match and therefore non-zero code
self.t.runError(("list",))
self.t.runError("list")
# Check that no task has been generated.
code, out, err = self.t(("task", "count"))
code, out, err = self.t("task count")
self.assertEqual("0", out.strip())
if __name__ == "__main__":

View File

@@ -1,86 +0,0 @@
#! /usr/bin/env perl
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
use strict;
use warnings;
use Test::More tests => 5;
# Ensure environment has no influence.
delete $ENV{'TASKDATA'};
delete $ENV{'TASKRC'};
use File::Basename;
my $ut = basename ($0);
my $rc = $ut . '.rc';
# Create the rc file.
if (open my $fh, '>', $rc)
{
print $fh "data.location=.\n",
"verbose=off\n",
"confirmation=no\n",
"defaultwidth=100\n",
"dateformat=m/d/Y\n",
"json.array=off";
close $fh;
}
# Add two tasks.
qx{../src/task rc:$rc add priority:H project:A -- one/1 2>&1};
qx{../src/task rc:$rc add +tag1 +tag2 two 2>&1};
# trip 1.
qx{../src/task rc:$rc export > roundtrip1.json 2>/dev/null};
ok (-s 'roundtrip1.json' > 0, "$ut: roundtrip1.json is not empty");
unlink 'pending.data', 'completed.data', 'undo.data', 'backlog.data';
qx{../src/task rc:$rc import roundtrip1.json 2>/dev/null};
# trip 2.
qx{../src/task rc:$rc export > roundtrip2.json 2>/dev/null};
ok (-s 'roundtrip2.json' > 0, "$ut: roundtrip2.json is not empty");
unlink 'pending.data', 'completed.data', 'undo.data', 'backlog.data';
qx{../src/task rc:$rc import roundtrip2.json 2>/dev/null};
# Examine.
#
# ID Created P Project Tags Description
# -- ---------- - ------- --------- -----------
# 1 1/7/2014 H A one/1
# 2 1/7/2014 tag1 tag2 two
my $output = qx{../src/task rc:$rc long 2>&1};
like ($output, qr/1\s+\d+\/\d+\/\d+.+\sH\s+A\s+one\/1/, "$ut: 2 round trips task 1 identical");
like ($output, qr/2\s+\d+\/\d+\/\d+.+\stag1\s+tag2\s+two/, "$ut: 2 round trips task 2 identical");
# Compare the actual JSON files.
$output = qx{diff roundtrip1.json roundtrip2.json 2>&1};
like ($output, qr/^$/, "$ut: JSON files roundtrip1.json and roundtrip2.json identical");
# Cleanup.
unlink qw(roundtrip1.json roundtrip2.json pending.data completed.data undo.data backlog.data), $rc;
exit 0;

View File

@@ -9,10 +9,16 @@ import argparse
import logging
import time
from multiprocessing import cpu_count
from Queue import Queue, Empty
from threading import Thread
from subprocess import call, Popen, PIPE
try:
# python 2
from Queue import Queue, Empty
except ImportError:
# python 3
from queue import Queue, Empty
# Look for taskd in $PATH instead of task/src/
os.environ["TASKD_USE_PATH"] = "1"
@@ -38,6 +44,9 @@ def run_test(testqueue, outqueue, threadname):
# Premature end
break
if sys.version_info > (3,):
out, err = out.decode('utf-8'), err.decode('utf-8')
output = ("# {0}\n".format(os.path.basename(test)), out, err)
log.debug("Collected output %s", output)
outqueue.put(output)
@@ -62,8 +71,8 @@ class TestRunner(object):
if os.access(test, os.X_OK):
# Executables only
if not cmd_args.serial:
with open(test) as fh:
if "/usr/bin/env python" in fh.readline():
with open(test, 'rb') as fh:
if b"/usr/bin/env python" in fh.read(50):
log.debug("Treating as parallel: %s", test)
self._parallelq.put(test)
else:
@@ -166,6 +175,7 @@ def parse_args():
parser.add_argument('--verbose', '-v', action="store_true",
help="Also send TAP output to stdout")
parser.add_argument('--logging', '-l', action="count",
default=0,
help="Logging level. -lll is the highest level")
parser.add_argument('--serial', action="store_true",
help="Do not run tests in parallel")

View File

@@ -41,15 +41,15 @@ class TestFilterPrefix(TestCase):
"""Executed once before any test in the class"""
cls.t = Task()
cls.t.config("verbose", "nothing")
cls.t(('add', 'foo'))
cls.t('add foo')
def test_success(self):
"""Test successful search returns zero."""
code, out, err = self.t(('list', '/foo/'))
code, out, err = self.t('list /foo/')
def test_failure(self):
"""Test failed search returns non-zero."""
code, out, err = self.t.runError(('list', '/bar/'))
code, out, err = self.t.runError('list /bar/')
if __name__ == "__main__":

View File

@@ -48,8 +48,7 @@ class MetaTests(type):
def test(self):
# ### Body of the usual test_testcase ### #
code, out, err = self.t(
("rc.report.{0}.sort:{1}".format(self._report, filter),
self._report)
"rc.report.{0}.sort:{1} {0}".format(self._report, filter)
)
for expected in expectations:
@@ -99,12 +98,12 @@ class TestSorting(TestCase):
# Report to use when running this class's tests
cls._report = "list"
cls.t(("add", "zero"))
cls.t(("add", "priority:H", "project:A", "due:yesterday", "one"))
cls.t(("add", "priority:M", "project:B", "due:today", "two"))
cls.t(("add", "priority:L", "project:C", "due:tomorrow", "three"))
cls.t(("add", "priority:H", "project:C", "due:today", "four"))
cls.t(("2", "start"))
cls.t("add zero")
cls.t("add priority:H project:A due:yesterday one")
cls.t("add priority:M project:B due:today two")
cls.t("add priority:L project:C due:tomorrow three")
cls.t("add priority:H project:C due:today four")
cls.t("2 start")
TESTS = {
# Filter # Expected matches/outputs
@@ -250,29 +249,19 @@ class TestBug438(TestCase):
# 2 tasks created in the past, and finished 20 seconds later
stamp = int(time.time())
cls.t(("add", "one older",
"entry:{0}".format(stamp)))
cls.t("add one older entry:{0}".format(stamp))
stamp += 1
cls.t(("add", "one newer",
"entry:{0}".format(stamp)))
cls.t("add one newer entry:{0}".format(stamp))
start = stamp + 10
cls.t(("add", "two older",
"entry:{0}".format(stamp),
"start:{0}".format(start)))
cls.t("add two older entry:{0} start:{1}".format(stamp, start))
start += 1
cls.t(("add", "two newer",
"entry:{0}".format(stamp),
"start:{0}".format(start)))
cls.t("add two newer entry:{0} start:{1}".format(stamp, start))
end = start + 10
cls.t(("log", "three older",
"entry:{0}".format(stamp),
"end:{0}".format(end)))
cls.t("log three older entry:{0} end:{1}".format(stamp, end))
end += 1
cls.t(("log", "three newer",
"entry:{0}".format(stamp),
"end:{0}".format(end)))
cls.t("log three newer entry:{0} end:{1}".format(stamp, end))
TESTS = {
"entry+": ["one older.+one newer"],

View File

@@ -41,7 +41,7 @@ def run_test(test):
def parse_args():
parser = argparse.ArgumentParser(description="Run Taskwarrior tests repeatedly")
parser.add_argument('--logging', '-l', action="count",
parser.add_argument('--logging', '-l', action="count", default=0,
help="Logging level. -lll is the highest level")
parser.add_argument('--repeat', metavar="N", type=int, default=100,
help="How many times to run each test (default: 100)")

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -40,89 +40,72 @@ class TestBug101(TestCase):
def setUp(self):
"""Executed before each test in the class"""
self.t = Task()
# Define report with truncated_count style
with open(self.t.taskrc, 'a') as fh:
fh.write("report.bug101.columns=description.truncated_count\n")
#Find screen width in order to generate long enough string
command = ("_get", "context.width")
code, out, err = self.t(command)
self.t.config("report.bug101.columns", "description.truncated_count")
# Find screen width in order to generate long enough string
code, out, err = self.t("_get context.width")
self.width = int(out)
#Since task strips leading and trailing spaces, for the purposes
#of these tests, ensure description contains no spaces so we know
#exactly what string we are expecting
# Since task strips leading and trailing spaces, for the purposes
# of these tests, ensure description contains no spaces so we know
# exactly what string we are expecting
self.short_description = "A_task_description_"
#Generate long string
# Generate long string
self.long_description = self.short_description * int(math.ceil(float(self.width)/len(self.short_description)))
def test_short_no_count(self):
"""Check short description with no annotations"""
command = ("add", self.short_description)
self.t(command)
self.t(("add", self.short_description))
command = ("bug101",)
code, out, err = self.t(command)
code, out, err = self.t("bug101")
expected = self.short_description
self.assertIn(expected, out)
def test_short_with_count(self):
"""Check short description with annotations"""
command = ("add", self.short_description)
self.t(command)
self.t(("add", self.short_description))
command = ("1", "annotate", "A task annotation")
self.t(command)
self.t("1 annotate 'A task annotation'")
command = ("bug101",)
code, out, err = self.t(command)
code, out, err = self.t("bug101")
expected = self.short_description + " [1]"
self.assertIn(expected, out)
def test_long_no_count(self):
"""Check long description with no annotations"""
command = ("add", self.long_description)
self.t(command)
self.t(("add", self.long_description))
command = ("bug101",)
code, out, err = self.t(command)
code, out, err = self.t("bug101")
expected = self.long_description[:(self.width - 3)] + "..."
self.assertIn(expected, out)
def test_long_with_count(self):
"""Check long description with annotations"""
command = ("add", self.long_description)
self.t(command)
self.t(("add", self.long_description))
command = ("1", "annotate", "A task annotation")
self.t(command)
self.t("1 annotate 'A task annotation'")
command = ("bug101",)
code, out, err = self.t(command)
code, out, err = self.t("bug101")
expected = self.long_description[:(self.width - 7)] + "... [1]"
self.assertIn(expected, out)
def test_long_with_double_digit_count(self):
"""Check long description with double digit amount of annotations"""
command = ("add", self.long_description)
self.t(command)
self.t(("add", self.long_description))
for a in range(10):
command = ("1", "annotate", "A task annotation")
self.t(command)
for i in range(10):
self.t("1 annotate 'A task annotation'")
command = ("bug101",)
code, out, err = self.t(command)
code, out, err = self.t("bug101")
expected = self.long_description[:(self.width - 8)] + "... [10]"
self.assertIn(expected, out)
def tearDown(self):
command = ("1", "delete")
self.t(command, "y\n")
if __name__ == "__main__":
from simpletap import TAPTestRunner

View File

@@ -17,15 +17,11 @@ class TestBug1262(TestCase):
def setUpClass(cls):
cls.t = Task()
command = ("add", "Buy oranges")
cls.t(command)
command = ("add", "Buy apples")
cls.t(command)
cls.t('add "Buy oranges"')
cls.t('add "Buy apples"')
cls.DEPS = ("1", "2")
command = ("add", "dep:" + ",".join(cls.DEPS), "Make fruit salad!")
cls.t(command)
cls.t("add dep:" + ",".join(cls.DEPS) + '"Make fruit salad!"')
def test_dependency_contains_matches_ID(self):
"""dep.contains matches task IDs"""
@@ -34,25 +30,24 @@ class TestBug1262(TestCase):
# fail, which means it's actually using the UUID.
# Still, it passes on most cases. Which is WRONG!.
for char in self.DEPS:
self.t(("list", "dep.contains:{0}".format(char)))
self.t("list dep.contains:{0}".format(char))
def test_dependency_contains_not_matches_other(self):
"""dep.contains matches other characters not present in ID nor UUID"""
for char in set(string.letters).difference(string.hexdigits):
self.t.runError(("list", "dep.contains:{0}".format(char)))
self.t.runError("list dep.contains:{0}".format(char))
def test_dependency_contains_not_UUID(self):
"""dep.contains matches characters in the tasks' UUIDs"""
# Get the UUID of the task with description "Buy"
command = ("uuid", "Buy")
code, out, err = self.t(command)
code, out, err = self.t("uuid Buy")
# Get only characters that show up in the UUID
uuid = {chr for chr in out.splitlines()[0] if chr in string.hexdigits}
for char in uuid:
if char not in self.DEPS:
self.t.runError(("list", "dep.contains:{0}".format(char)))
self.t.runError("list dep.contains:{0}".format(char))
if __name__ == "__main__":

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -43,12 +43,12 @@ class TestBug1300(TestCase):
def test_dom_exit_status_good(self):
"""If the DOM recognizes a reference, it should return '0'
"""
self.t(("_get", "context.program"))
self.t("_get context.program")
def test_dom_exit_status_bad(self):
"""If the DOM does not recognize a reference, it should return '1'
"""
self.t.runError(("_get", "XYZ"))
self.t.runError("_get XYZ")
if __name__ == "__main__":

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -40,8 +40,8 @@ class TestBug1306(TestCase):
def test_mod_before_add(self):
"""FILTER before 'add' command upgraded to MODIFICATION"""
self.t(("project:PROJ", "add", "foo"))
code, out, err = self.t(("1", "info"))
self.t("project:PROJ add foo")
code, out, err = self.t("1 info")
self.assertIn("PROJ", out)
if __name__ == "__main__":

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -40,9 +40,9 @@ class TestBug1359(TestCase):
def test_add_hyphenated(self):
""""one-two-three" in description triggers Malformed ID error"""
self.t(("add", "'one-two-three.ca'"))
self.t("add 'one-two-three.ca'")
code, out, err = self.t(("1", "info"))
code, out, err = self.t("1 info")
self.assertIn("one-two-three.ca", out)
if __name__ == "__main__":

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -40,8 +40,8 @@ class TestBug1377(TestCase):
def test_bad_tag_parser(self):
"""Task doesn't accept tags in default.command"""
self.t(("add", "Something interesting"))
self.t(("add", "dep:1", "NOTSHOWN"))
self.t("add Something interesting")
self.t("add dep:1 NOTSHOWN")
self.t.config("default.command", "next -BLOCKED")
code, out, err = self.t()

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -56,84 +56,84 @@ class TestBug1379(TestCase):
"""color.tag.BLOCKED changes color of BLOCKED tasks"""
self.t.config("color.tag.BLOCKED", "red")
self.t(("add", "Blocks"))
self.t(("add", "dep:1", "Blocked"))
self.t("add Blocks")
self.t("add dep:1 Blocked")
code, out, err = self.t(("all", "+BLOCKED"))
code, out, err = self.t("all +BLOCKED")
self.assertRegexpMatches(out, self.RED + r".*Blocked.*" + self.CLEAR)
def test_color_UNBLOCKED(self):
"""color.tag.UNBLOCKED changes color of UNBLOCKED tasks"""
self.t.config("color.tag.UNBLOCKED", "red")
self.t(("add", "Blocks"))
self.t(("add", "dep:1", "Blocked"))
self.t("add Blocks")
self.t("add dep:1 Blocked")
code, out, err = self.t(("all", "+UNBLOCKED"))
code, out, err = self.t("all +UNBLOCKED")
self.assertRegexpMatches(out, self.RED + r".*Blocks.*" + self.CLEAR)
def test_color_BLOCKING(self):
"""color.tag.BLOCKING changes color of BLOCKING tasks"""
self.t.config("color.tag.BLOCKING", "red")
self.t(("add", "Blocks"))
self.t(("add", "dep:1", "Blocked"))
self.t("add Blocks")
self.t("add dep:1 Blocked")
code, out, err = self.t(("all", "+BLOCKING"))
code, out, err = self.t("all +BLOCKING")
self.assertRegexpMatches(out, self.RED + r".*Blocks.*" + self.CLEAR)
def test_color_SCHEDULED(self):
"""color.tag.SCHEDULED changes color of SCHEDULED tasks"""
self.t.config("color.tag.SCHEDULED", "red")
self.t(("add", "scheduled:tomorrow", "Have fun"))
self.t("add scheduled:tomorrow Have fun")
code, out, err = self.t(("all", "+SCHEDULED"))
code, out, err = self.t("all +SCHEDULED")
self.assertRegexpMatches(out, self.RED + r".*Have fun.*" + self.CLEAR)
def test_color_UNTIL(self):
"""color.tag.UNTIL changes color of UNTIL tasks"""
self.t.config("color.tag.UNTIL", "red")
self.t(("add", "until:tomorrow", "Urgent"))
self.t("add until:tomorrow Urgent")
code, out, err = self.t(("all", "+UNTIL"))
code, out, err = self.t("all +UNTIL")
self.assertRegexpMatches(out, self.RED + r".*Urgent.*" + self.CLEAR)
def test_color_WAITING(self):
"""color.tag.WAITING changes color of WAITING tasks"""
self.t.config("color.tag.WAITING", "red")
self.t(("add", "wait:tomorrow", "Tomorrow"))
self.t("add wait:tomorrow Tomorrow")
code, out, err = self.t(("all", "+WAITING"))
code, out, err = self.t("all +WAITING")
self.assertRegexpMatches(out, self.RED + r".*Tomorrow.*" + self.CLEAR)
def test_color_PARENT(self):
"""color.tag.PARENT changes color of PARENT tasks"""
self.t.config("color.tag.PARENT", "red")
self.t(("add", "recur:daily", "due:tomorrow", "Email"))
self.t("add recur:daily due:tomorrow Email")
code, out, err = self.t(("all", "+PARENT"))
code, out, err = self.t("all +PARENT")
self.assertRegexpMatches(out, self.RED + r".*Email.*" + self.CLEAR)
def test_color_CHILD(self):
"""color.tag.CHILD changes color of CHILD tasks"""
self.t.config("color.tag.CHILD", "red")
self.t(("add", "recur:daily", "due:tomorrow", "Email"))
self.t("add recur:daily due:tomorrow Email")
code, out, err = self.t(("all", "+CHILD"))
code, out, err = self.t("all +CHILD")
self.assertRegexpMatches(out, self.RED + r".*Email.*" + self.CLEAR)
def test_color_PENDING(self):
"""color.tag.PENDING changes color of PENDING tasks"""
self.t.config("color.tag.PENDING", "red")
self.t(("add", "Pending"))
self.t("add Pending")
code, out, err = self.t(("all", "+PENDING"))
code, out, err = self.t("all +PENDING")
self.assertRegexpMatches(out, self.RED + r".*Pending.*" + self.CLEAR)
def test_color_COMPLETED(self):
@@ -141,10 +141,10 @@ class TestBug1379(TestCase):
self.t.config("color.tag.COMPLETED", "red")
self.t.config("color.completed", "")
self.t(("add", "Complete"))
self.t(("1", "done"))
self.t("add Complete")
self.t("1 done")
code, out, err = self.t(("all", "+COMPLETED"))
code, out, err = self.t("all +COMPLETED")
self.assertRegexpMatches(out, self.RED + r".*Complete.*" + self.CLEAR)
def test_color_DELETED(self):
@@ -152,10 +152,10 @@ class TestBug1379(TestCase):
self.t.config("color.tag.DELETED", "red")
self.t.config("color.deleted", "")
self.t(("add", "Delete"))
self.t(("1", "delete"))
self.t("add Delete")
self.t("1 delete")
code, out, err = self.t(("all", "+DELETED"))
code, out, err = self.t("all +DELETED")
self.assertRegexpMatches(out, self.RED + r".*Delete.*" + self.CLEAR)
if __name__ == "__main__":

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -40,9 +40,9 @@ class TestBug1381(TestCase):
def test_blocking(self):
"""Blocking report displays tasks that are blocking other tasks"""
self.t(("add", "blocks"))
self.t(("add", "dep:1", "blocked"))
code, out, err = self.t(("blocking",))
self.t("add blocks")
self.t("add dep:1 blocked")
code, out, err = self.t("blocking")
self.assertIn("blocks", out)

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -44,19 +44,19 @@ class TestBug1414(TestCase):
def test_execute(self):
"""use execute"""
code, out, err = self.t(("exec", "echo hello"))
code, out, err = self.t("exec echo hello")
self.assertIn("hello", out)
def test_exec_alias(self):
"""use exec in alias"""
self.t.config("alias.asdf", "exec echo hello")
code, out, err = self.t(("asdf", ""))
code, out, err = self.t("asdf")
self.assertIn("hello", out)
def test_execute_alias(self):
"""use execute in alias"""
self.t.config("alias.asdf", "execute echo hello")
code, out, err = self.t(("asdf", ""))
code, out, err = self.t("asdf")
self.assertIn("hello", out)
def test_default_command(self):

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -42,20 +42,20 @@ class Test1418(TestCase):
# Helper methods
def find_in_list(self, description):
code, out, err = self.t(("list",))
code, out, err = self.t("list")
self.assertIn(description, out)
def search_task_pattern(self, description):
command = ("/" + description.replace("/", "\\/") + "/",)
command = "/" + description.replace("/", "\\/") + "/"
code, out, err = self.t(command)
self.assertIn(description, out)
def add_search_task(self, description):
command = ("add", description)
command = "add " + description
self.t(command)
def add_search_task_description(self, description):
command = ("add", "description:'" + description + "'")
command = "add description:'" + description + "'"
self.t(command)
def test_slash_in_description(self):
@@ -108,7 +108,7 @@ class Test1418(TestCase):
# Different from the other tests, because we want to escape the '+'
# in the regex, but not in the 'add' or 'list'
code, out, err = self.t(("/foo\\+/",))
code, out, err = self.t("/foo\\+/")
self.assertIn(description, out)
if __name__ == "__main__":

View File

@@ -43,8 +43,8 @@ class Test1424(TestCase):
def test_1824_days(self):
"""Check that due:1824d works"""
self.t(('add', 'foo', 'due:1824d'))
code, out, err = self.t(('_get', '1.due.year'))
self.t('add foo due:1824d')
code, out, err = self.t('_get 1.due.year')
# NOTE This test has a possible race condition when run "during" EOY.
# If Taskwarrior is executed at 23:59:59 on new year's eve and the
# python code below runs at 00:00:00 on new year's day, the two will
@@ -55,8 +55,8 @@ class Test1424(TestCase):
def test_3648_days(self):
"""Check that due:3648d works"""
self.t(('add', 'foo', 'due:3648d'))
code, out, err = self.t(('_get', '1.due.year'))
self.t('add foo due:3648d')
code, out, err = self.t('_get 1.due.year')
# NOTE This test has a possible race condition when run "during" EOY.
# If Taskwarrior is executed at 23:59:59 on new year's eve and the
# python code below runs at 00:00:00 on new year's day, the two will

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -62,7 +62,7 @@ class TestBug1436(TestCase):
code, out, err = self.t("add Use this backslash \\\\\\\\")
self.assertIn("Created task 1", out)
code, out, err = self.t(("list",))
code, out, err = self.t("list")
self.assertIn("Use this backslash \\", out)
def test_backslashes(self):

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -42,16 +42,14 @@ class TestBug1438(TestCase):
def test_recurring_tasks_shouldn_ask_for_confirmation(self):
"""rc.confirmation=off still prompts while changing recurring tasks"""
command = ("add", "Sometimes", "due:tomorrow", "recur:daily",)
code, out, err = self.t(command)
code, out, err = self.t("add Sometimes due:tomorrow recur:daily")
self.assertIn("Created task 1", out)
code, out, err = self.t(("list",))
code, out, err = self.t("list")
self.assertIn("Sometimes", out)
command = ("rc.confirmation=off", "rc.recurrence.confirmation=off", "2", "mod", "/Sometimes/Everytime/")
code, out, err = self.t(command)
code, out, err = self.t("rc.confirmation=off rc.recurrence.confirmation=off 2 mod /Sometimes/Everytime/")
self.assertIn("Modified 1 task", out)
code, out, err = self.t(("list",))
code, out, err = self.t("list")
self.assertIn("Everytime", out)

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -41,8 +41,7 @@ class TestBug1441(TestCase):
def test_import_filename(self):
"""import fails if file doesn't exist"""
command = ("import", "xxx_doesnotexist")
code, out, err = self.t.runError(command)
code, out, err = self.t.runError("import xxx_doesnotexist")
self.assertIn("File 'xxx_doesnotexist' not found.", err)

View File

@@ -44,16 +44,16 @@ class Test1445(TestCase):
def test_alias_single_word(self):
"""Verify single-word aliases"""
self.t.config('alias.when', 'execute date')
code, out, err = self.t(('when',))
code, out, err = self.t('when')
self.assertEqual(0, code, "Exit code was non-zero ({0})".format(code))
self.assertIn(str(datetime.now().year), out)
def test_alias_multi_word(self):
"""Verify multi-word aliases"""
self.t.config('alias.worktasks', 'list +work')
self.t(('add', 'one', '+work'))
self.t(('add', 'two'))
code, out, err = self.t(('worktasks',))
self.t('add one +work')
self.t('add two')
code, out, err = self.t('worktasks')
self.assertEqual(0, code, "Exit code was non-zero ({0})".format(code))
self.assertIn('one', out)

View File

@@ -43,9 +43,9 @@ class Test1447(TestCase):
def test_filter_uda(self):
"""Verify single-word aliases"""
self.t.config('uda.sep.type', 'string')
self.t(('add', 'one'))
self.t(('add', 'two', 'sep:foo'))
code, out, err = self.t(('sep:', 'list'))
self.t('add one')
self.t('add two sep:foo')
code, out, err = self.t('sep: list')
self.assertEqual(0, code, "Exit code was non-zero ({0})".format(code))
self.assertIn('one', out)

View File

@@ -40,23 +40,19 @@ from basetest import Task, TestCase
class Test1469(TestCase):
def setUp(self):
self.t = Task()
self.t(('add', 'foo'))
self.t(('add', 'neue Badmöbel kaufen'))
self.t('add foo')
self.t('add "neue Badmöbel kaufen"')
def test_implicit_search_sensitive_regex(self):
"""Implicit search, case sensitive, regex """
code, out, err = self.t(('list', '/möbel/',
'rc.search.case.sensitive=yes',
'rc.regex=on'))
code, out, err = self.t('list /möbel/ rc.search.case.sensitive=yes rc.regex=on')
self.assertEqual(0, code, "Exit code was non-zero ({0})".format(code))
self.assertIn('möbel', out)
self.assertNotIn('foo', out)
def test_implicit_search_sensitive_noregex(self):
"""Implicit search, case sensitive, no regex """
code, out, err = self.t(('list', '/möbel/',
'rc.search.case.sensitive=yes',
'rc.regex=off'))
code, out, err = self.t('list /möbel/ rc.search.case.sensitive=yes rc.regex=off')
self.assertEqual(0, code, "Exit code was non-zero ({0})".format(code))
self.assertIn('möbel', out)
self.assertNotIn('foo', out)
@@ -64,9 +60,7 @@ class Test1469(TestCase):
@unittest.skipIf('CYGWIN' in platform.system(), 'Skipping regex case-insensitive test for Cygwin')
def test_implicit_search_insensitive_regex(self):
"""Implicit search, case insensitive, regex """
code, out, err = self.t(('list', '/möbel/',
'rc.search.case.sensitive=no',
'rc.regex=on'))
code, out, err = self.t('list /möbel/ rc.search.case.sensitive=no rc.regex=on')
self.assertEqual(0, code,
"Exit code was non-zero ({0})".format(code))
self.assertIn('möbel', out)
@@ -74,27 +68,21 @@ class Test1469(TestCase):
def test_implicit_search_insensitive_noregex(self):
"""Implicit search, case insensitive, no regex """
code, out, err = self.t(('list', '/möbel/',
'rc.search.case.sensitive=no',
'rc.regex=off'))
code, out, err = self.t('list /möbel/ rc.search.case.sensitive=no rc.regex=off')
self.assertEqual(0, code, "Exit code was non-zero ({0})".format(code))
self.assertIn('möbel', out)
self.assertNotIn('foo', out)
def test_explicit_search_sensitive_regex(self):
"""Explicit search, case sensitive, regex """
code, out, err = self.t(('list', '/möbel/',
'rc.search.case.sensitive=yes',
'rc.regex=on'))
code, out, err = self.t('list /möbel/ rc.search.case.sensitive=yes rc.regex=on')
self.assertEqual(0, code, "Exit code was non-zero ({0})".format(code))
self.assertIn('möbel', out)
self.assertNotIn('foo', out)
def test_explicit_search_sensitive_noregex(self):
"""Explicit search, case sensitive, no regex """
code, out, err = self.t(('list', '/möbel/',
'rc.search.case.sensitive=yes',
'rc.regex=off'))
code, out, err = self.t('list /möbel/ rc.search.case.sensitive=yes rc.regex=off')
self.assertEqual(0, code, "Exit code was non-zero ({0})".format(code))
self.assertIn('möbel', out)
self.assertNotIn('foo', out)
@@ -102,18 +90,14 @@ class Test1469(TestCase):
@unittest.skipIf('CYGWIN' in platform.system(), 'Skipping regex case-insensitive test for Cygwin')
def test_explicit_search_insensitive_regex(self):
"""Explicit search, case insensitive, regex """
code, out, err = self.t(('list', '/möbel/',
'rc.search.case.sensitive=no',
'rc.regex=on'))
code, out, err = self.t('list /möbel/ rc.search.case.sensitive=no rc.regex=on')
self.assertEqual(0, code, "Exit code was non-zero ({0})".format(code))
self.assertIn('möbel', out)
self.assertNotIn('foo', out)
def test_explicit_search_insensitive_noregex(self):
"""Explicit search, case insensitive, no regex """
code, out, err = self.t(('list', '/möbel/',
'rc.search.case.sensitive=no',
'rc.regex=off'))
code, out, err = self.t('list /möbel/ rc.search.case.sensitive=no rc.regex=off')
self.assertEqual(0, code, "Exit code was non-zero ({0})".format(code))
self.assertIn('möbel', out)
self.assertNotIn('foo', out)

View File

@@ -44,10 +44,10 @@ class Test1486(TestCase):
"""Verify waiting report shows waiting tasks"""
self.t.config('uda.sep.type', 'string')
self.t(('add', 'regular'))
self.t(('add', 'waited', 'wait:later'))
self.t('add regular')
self.t('add waited wait:later')
code, out, err = self.t(('waiting',))
code, out, err = self.t('waiting')
self.assertEqual(0, code, "Exit code was non-zero ({0})".format(code))
self.assertIn('waited', out)
self.assertNotIn('regular', out)

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -35,6 +35,7 @@ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from basetest import Task, TestCase
class Test1510(TestCase):
def setUp(self):
self.t = Task()
@@ -52,8 +53,8 @@ class Test1510(TestCase):
backlog.data with empty string value
"""
self.t(('add', 'test', 'due:2015-05-05'))
self.t(('1', 'mod', 'due:'))
self.t('add test due:2015-05-05')
self.t('1 mod due:')
self.assertNoEmptyValueInBacklog('due')
def test_no_empty_value_for_empty_priority_in_backlog(self):
@@ -62,10 +63,10 @@ class Test1510(TestCase):
backlog.data with empty string value
"""
self.t(('add', 'test', 'pri:""'))
self.t(('add', 'test2', "pri:''"))
self.t(('add', 'test3', "pri:"))
self.t(('add', 'test4', "pri:H"))
self.t('add test pri:""')
self.t("add test2 pri:''")
self.t("add test3 pri:")
self.t("add test4 pri:H")
self.assertNoEmptyValueInBacklog('priority')
def test_no_empty_value_for_empty_project_in_backlog(self):
@@ -74,10 +75,10 @@ class Test1510(TestCase):
backlog.data with empty string value
"""
self.t(('add', 'test', 'project:""'))
self.t(('add', 'test2', "project:''"))
self.t(('add', 'test3', "project:"))
self.t(('add', 'test4', "project:random"))
self.t('add test project:""')
self.t("add test2 project:''")
self.t("add test3 project:")
self.t("add test4 project:random")
self.assertNoEmptyValueInBacklog('project')
if __name__ == "__main__":

View File

@@ -1,39 +1,38 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
import unittest
from datetime import datetime
# Ensure python finds the local simpletap module
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from basetest import Task, TestCase, Taskd, ServerTestCase
from basetest import Task, TestCase
class TestBug1527(TestCase):

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -46,8 +46,8 @@ class Test1542(TestCase):
Make sure the numeric UDA value 1187962 does not get converted to
scientific notation on export.
"""
self.t(('add', 'large', 'bugid:1187962'))
code, out, err = self.t(('1', 'export'))
self.t('add large bugid:1187962')
code, out, err = self.t('1 export')
self.assertIn("\"bugid\":1187962,", out)
def test_small_numeric_uda_retains_value(self):
@@ -55,8 +55,8 @@ class Test1542(TestCase):
Make sure the numeric UDA value 43.21 does not get converted to
integer on export.
"""
self.t(('add', 'small', 'bugid:43.21'))
code, out, err = self.t(('1', 'export'))
self.t('add small bugid:43.21')
code, out, err = self.t('1 export')
self.assertIn("\"bugid\":43.21", out)
if __name__ == "__main__":

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -35,6 +35,7 @@ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from basetest import Task, TestCase
class Test1549(TestCase):
def setUp(self):
self.t = Task()
@@ -51,7 +52,7 @@ class Test1549(TestCase):
"""
# This command will hang and therefore timeout in 2.4.1.
code, out, err = self.t(('add', '1e x'))
code, out, err = self.t('add 1e x')
self.assertIn("Created task 1.", out)

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -43,8 +43,8 @@ class TestBug21(TestCase):
self.t.config('uda.foo.type', 'string')
self.t.config('uda.foo.label', 'FOO')
self.t(("add", "this", "is", "a", "foo", "bar"))
code, out, err = self.t(("1", "info"))
self.t("add this is a foo bar")
code, out, err = self.t("1 info")
self.assertIn("this is a foo bar", out)

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -41,30 +41,25 @@ class TestBug252(TestCase):
def test_done_stop(self):
"""done should also stop a task timer"""
command = ("add", "Timeit")
code, out, err = self.t(command)
code, out, err = self.t("add Timeit")
# Starting the newly added task
command = ("1", "start")
code, out, err = self.t(command)
code, out, err = self.t("1 start")
notexpected = "Start deleted"
self.assertNotIn(notexpected, out)
# Completing the task should also stop the timer
command = ("1", "done")
code, out, err = self.t(command)
code, out, err = self.t("1 done")
# Confirm that "start" was removed
command = ("1", "info")
code, out, err = self.t(command)
code, out, err = self.t("1 info")
expected = "Start deleted"
self.assertIn(expected, out)
# Confirm that the timer was indeed stopped
command = ("1", "stop")
code, out, err = self.t.runError(command)
code, out, err = self.t.runError("1 stop")
expected = "Task 1 'Timeit' not started."
self.assertIn(expected, out)

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -41,75 +41,63 @@ class TestBug262(TestCase):
cls.t = Task()
cls.absent = "Taskwarrior project"
command = ("add", "proj:tw", cls.absent)
cls.t(command)
cls.t(("add", "proj:tw", cls.absent))
cls.present = "Another project"
command = ("add", "proj:something_else", cls.present)
cls.t(command)
cls.t(("add", "proj:something_else", cls.present))
def _check_expectation(self, command):
code, out, err = self.t(command)
# Add quotes to ensure spaces around are not split by the shell lexer
code, out, err = self.t((command,))
self.assertIn(self.present, out)
self.assertNotIn(self.absent, out)
def test_proj_isnt(self):
"""project.isnt works"""
command = ("project.isnt:tw",)
self._check_expectation(command)
self._check_expectation("project.isnt:tw")
def test_proj_isnt_spaces(self):
"""project.isnt works if wrapped in spaces"""
command = (" project.isnt:tw ",)
self._check_expectation(command)
self._check_expectation(" project.isnt:tw ")
def test_proj_isnt_space_leading(self):
"""project.isnt works if leading space is present"""
command = (" project.isnt:tw",)
self._check_expectation(command)
self._check_expectation(" project.isnt:tw")
def test_proj_isnt_space_trailing(self):
"""project.isnt works if trailing space is present"""
command = ("project.isnt:tw ",)
self._check_expectation(command)
self._check_expectation("project.isnt:tw ")
def test_proj_isnt_parenthesis(self):
"""project.isnt works within parenthesis"""
command = ("(project.isnt:tw)",)
self._check_expectation(command)
self._check_expectation("(project.isnt:tw)")
def test_proj_isnt_parenthesis_space_leading(self):
"""project.isnt works within parenthesis after a leading space"""
command = (" (project.isnt:tw)",)
self._check_expectation(command)
self._check_expectation(" (project.isnt:tw)")
def test_proj_isnt_parenthesis_space_leading_double(self):
"""project.isnt works within parenthesis after a double leading space
"""
command = (" ( project.isnt:tw)",)
self._check_expectation(command)
self._check_expectation(" ( project.isnt:tw)")
def test_proj_isnt_parenthesis_space_trailing(self):
"""project.isnt works within parenthesis after a trailing space"""
command = ("(project.isnt:tw) ",)
self._check_expectation(command)
self._check_expectation("(project.isnt:tw) ")
def test_proj_isnt_parenthesis_space_trailing_double(self):
"""project.isnt works within parenthesis after a double trailing space
"""
command = ("(project.isnt:tw ) ",)
self._check_expectation(command)
self._check_expectation("(project.isnt:tw ) ")
def test_proj_isnt_spaces_parenthesis(self):
"""project.isnt works within parenthesis and spaces"""
command = (" (project.isnt:tw) ",)
self._check_expectation(command)
self._check_expectation(" (project.isnt:tw) ")
def test_proj_isnt_spaces_parenthesis_double(self):
"""project.isnt works within parenthesis and double spaces"""
command = (" ( project.isnt:tw ) ",)
self._check_expectation(command)
self._check_expectation(" ( project.isnt:tw ) ")
if __name__ == "__main__":
from simpletap import TAPTestRunner

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -41,10 +41,10 @@ class TestBug268(TestCase):
def test_add_hyphenated(self):
"""escaped backslashes do not work with 'modify'"""
self.t(("add", "a", "b", "or", "c"))
self.t(("1", "modify", "/a b/a\/b/"))
self.t("add a b or c")
self.t('1 modify "/a b/a\/b/"')
code, out, err = self.t(("1", "info"))
code, out, err = self.t("1 info")
self.assertIn("a/b or c", out)

View File

@@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
################################################################################
##
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included
## in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
##
## http://www.opensource.org/licenses/mit-license.php
##
################################################################################
###############################################################################
#
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# http://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import sys
import os
@@ -50,42 +50,42 @@ class Test285(TestCase):
# due:1month - - - - - - - ?
# due:1year - - - - - - - -
cls.t(('add', 'due_last_week', 'due:-1week'))
cls.t(('add', 'due_yesterday', 'due:-1day'))
cls.t(('add', 'due_earlier_today', 'due:today'))
cls.t(('add', 'due_later_today', 'due:tomorrow'))
cls.t(('add', 'due_three_days', 'due:3days'))
cls.t(('add', 'due_next_month', 'due:1month'))
cls.t(('add', 'due_next_year', 'due:1year'))
cls.t('add due_last_week due:-1week')
cls.t('add due_yesterday due:-1day')
cls.t('add due_earlier_today due:today')
cls.t('add due_later_today due:tomorrow')
cls.t('add due_three_days due:3days')
cls.t('add due_next_month due:1month')
cls.t('add due_next_year due:1year')
def test_overdue(self):
"""+OVERDUE"""
code, out, err = self.t(("+OVERDUE", "count"))
code, out, err = self.t("+OVERDUE count")
self.assertEqual(out, "3\n", "+OVERDUE == 3 tasks")
def test_yesterday(self):
"""+YESTERDAY"""
code, out, err = self.t(("+YESTERDAY", "count"))
code, out, err = self.t("+YESTERDAY count")
self.assertEqual(out, "1\n", "+YESTERDAY == 1 task")
def test_due(self):
"""+DUE"""
code, out, err = self.t(("+DUE", "count"))
code, out, err = self.t("+DUE count")
self.assertEqual(out, "3\n", "+DUE == 3 task")
def test_today(self):
"""+TODAY"""
code, out, err = self.t(("+TODAY", "count"))
code, out, err = self.t("+TODAY count")
self.assertEqual(out, "1\n", "+TODAY == 1 task")
def test_duetoday(self):
"""+DUETODAY"""
code, out, err = self.t(("+DUETODAY", "count"))
code, out, err = self.t("+DUETODAY count")
self.assertEqual(out, "1\n", "+DUETODAY == 1 task")
def test_tomorrow(self):
"""+TOMORROW"""
code, out, err = self.t(("+TOMORROW", "count"))
code, out, err = self.t("+TOMORROW count")
self.assertEqual(out, "1\n", "+TOMORROW == 1 task")

View File

@@ -52,18 +52,18 @@ class TestUdaReports(TestCase):
cls.t.config("report.bad.labels", "ID,Extra2")
cls.t.config("report.bad.sort", "ID")
cls.t(("add", "one", "extra:foo"))
cls.t("add one extra:foo")
def test_uda_show_report(self):
"""UDA shown in report"""
code, out, err = self.t(("good",))
code, out, err = self.t("good")
self.assertIn("foo", out)
def test_uda_no_show_report(self):
"""UDA not shown in report"""
code, out, err = self.t.runError(("bad",))
code, out, err = self.t.runError("bad")
self.assertNotIn("foo", out)
self.assertIn("Unrecognized column name", err)

View File

@@ -44,15 +44,15 @@ class TestUDACustomSort(TestCase):
cls.t.config('uda.foo.values', 'H,M,L,')
cls.t.config('report.list.columns', 'id,description,foo')
cls.t.config('report.list.labels', 'ID,Desc,Foo')
cls.t(('add', 'four', 'foo:H'))
cls.t(('add', 'three', 'foo:M'))
cls.t(('add', 'two', 'foo:L'))
cls.t(('add', 'one'))
cls.t('add four foo:H')
cls.t('add three foo:M')
cls.t('add two foo:L')
cls.t('add one')
def test_ascending(self):
"""Ascending sort order"""
self.t.config('uda.foo.values', 'H,M,L,')
code, out, err = self.t(('rc.report.list.sort:foo+', 'list'))
code, out, err = self.t('rc.report.list.sort:foo+ list')
one = out.find('one')
two = out.find('two')
@@ -66,7 +66,7 @@ class TestUDACustomSort(TestCase):
def test_descending(self):
"""Descending sort order"""
self.t.config('uda.foo.values', 'H,M,L,')
code, out, err = self.t(('rc.report.list.sort:foo-', 'list'))
code, out, err = self.t('rc.report.list.sort:foo- list')
one = out.find('one')
two = out.find('two')
@@ -80,7 +80,7 @@ class TestUDACustomSort(TestCase):
def test_ridiculous(self):
"""Ridiculous sort order"""
self.t.config('uda.foo.values', 'H,M,,L')
code, out, err = self.t(('rc.report.list.sort:foo-', 'list'))
code, out, err = self.t('rc.report.list.sort:foo- list')
one = out.find('one')
two = out.find('two')

View File

@@ -42,23 +42,23 @@ class TestUndo(TestCase):
def test_add_undo(self):
"""'add' then 'undo'"""
code, out, err = self.t(('add', 'one'))
code, out, err = self.t(('_get', '1.status'))
code, out, err = self.t('add one')
code, out, err = self.t('_get 1.status')
self.assertEqual(out.strip(), 'pending')
code, out, err = self.t(('undo'))
code, out, err = self.t(('_get', '1.status'))
code, out, err = self.t('undo')
code, out, err = self.t('_get 1.status')
self.assertEqual(out.strip(), '')
def test_add_done_undo(self):
"""'add' then 'done' then 'undo'"""
code, out, err = self.t(('add', 'two'))
code, out, err = self.t(('_get', '1.status'))
code, out, err = self.t('add two')
code, out, err = self.t('_get 1.status')
self.assertEqual(out.strip(), 'pending')
code, out, err = self.t(('1', 'done'))
code, out, err = self.t(('_get', '1.status'))
code, out, err = self.t('1 done')
code, out, err = self.t('_get 1.status')
self.assertEqual(out.strip(), 'completed')
code, out, err = self.t(('undo'))
code, out, err = self.t(('_get', '1.status'))
code, out, err = self.t('undo')
code, out, err = self.t('_get 1.status')
self.assertEqual(out.strip(), 'pending')
def test_undo_en_passant(self):

View File

@@ -41,20 +41,20 @@ class TestUpgrade(TestCase):
def test_upgrade_to_recurring(self):
"""Upgrade a task to recurring"""
self.t(("add", "one"))
self.t("add one")
code, out, err = self.t(("1", "info"))
code, out, err = self.t("1 info")
self.assertRegexpMatches(out, "Status\s+Pending")
self.t(("1", "modify", "due:tomorrow", "recur:weekly"))
self.t(("list",))
self.t("1 modify due:tomorrow recur:weekly")
self.t("list")
code, out, err = self.t(("1", "info"))
code, out, err = self.t("1 info")
self.assertRegexpMatches(out, "Status\s+Recurring")
self.assertRegexpMatches(out, "Recurrence\s+weekly")
# Also check for the presence of a children task with pending state
code, out, err = self.t(("2", "info"))
code, out, err = self.t("2 info")
self.assertRegexpMatches(out, "Status\s+Pending")
self.assertRegexpMatches(out, "Recurrence\s+weekly")

View File

@@ -43,16 +43,16 @@ class TestVerbosity(TestCase):
self.t = Task()
self.t.config("print.empty.columns", "yes")
self.t(("add", "Sample"))
self.t("add Sample")
# TODO Verbosity: 'edit'
def test_verbosity_new_id(self):
"""Verbosity new-id"""
code, out, err = self.t(("rc.verbose:new-id", "add", "Sample1"))
code, out, err = self.t("rc.verbose:new-id add Sample1")
self.assertRegexpMatches(out, r"Created task \d")
code, out, err = self.t(("rc.verbose:nothing", "add", "Sample2"))
code, out, err = self.t("rc.verbose:nothing add Sample2")
self.assertNotRegexpMatches(out, r"Created task \d")
def test_verbosity_new_uuid(self):
@@ -62,7 +62,7 @@ class TestVerbosity(TestCase):
def test_verbosity_label(self):
"""Verbosity label"""
code, out, err = self.t(("rc.verbose:label", "ls"))
code, out, err = self.t("rc.verbose:label ls")
self.assertRegexpMatches(
out,
"ID.+A.+D.+Project.+Tags.+R.+Wait.+S.+Due.+Until.+Description"
@@ -70,14 +70,14 @@ class TestVerbosity(TestCase):
def test_verbosity_affected(self):
"""Verbosity affected"""
code, out, err = self.t(("rc.verbose:affected", "ls"))
code, out, err = self.t("rc.verbose:affected ls")
expected = re.compile(r"^\d+ tasks?$", re.MULTILINE)
self.assertRegexpMatches(out, expected)
def test_verbosity_off(self):
"""Verbosity off"""
code, out, err = self.t(("rc.verbose:nothing", "ls"))
code, out, err = self.t("rc.verbose:nothing ls")
expected = re.compile(r"^\d+ tasks?$", re.MULTILINE)
self.assertNotRegexpMatches(out, expected)
@@ -85,7 +85,7 @@ class TestVerbosity(TestCase):
def test_verbosity_special(self):
"""Verbosity special"""
code, out, err = self.t(("rc.verbose:special", "1", "mod", "+next"))
code, out, err = self.t("rc.verbose:special 1 mod +next")
self.assertIn("The 'next' special tag will boost the urgency of this "
"task so it appears on the 'next' report.", out)
@@ -96,30 +96,30 @@ class TestVerbosity(TestCase):
def count_blank_lines(x):
return len(filter(operator.not_, x.splitlines()))
code, out, err = self.t(("rc.verbose:nothing", "ls"))
code, out, err = self.t("rc.verbose:nothing ls")
self.assertEqual(count_blank_lines(out), 0)
code, out, err = self.t(("rc.verbose:blank", "ls"))
code, out, err = self.t("rc.verbose:blank ls")
self.assertEqual(count_blank_lines(out), 2)
def test_verbosity_header(self):
"""Verbosity header"""
code, out, err = self.t(("rc.verbose:nothing", "ls"))
code, out, err = self.t("rc.verbose:nothing ls")
self.assertNotIn("TASKRC override:", err)
self.assertNotIn("TASKDATA override:", err)
code, out, err = self.t(("rc.verbose:header", "ls"))
code, out, err = self.t("rc.verbose:header ls")
self.assertIn("TASKRC override:", err)
self.assertIn("TASKDATA override:", err)
def test_verbosity_project(self):
"""Verbosity project"""
code, out, err = self.t(("rc.verbose:nothing", "add", "proj:T", "one"))
code, out, err = self.t("rc.verbose:nothing add proj:T one")
self.assertNotIn("The project 'T' has changed.", err)
code, out, err = self.t(("rc.verbose:project", "add", "proj:T", "two"))
code, out, err = self.t("rc.verbose:project add proj:T two")
self.assertIn("The project 'T' has changed.", err)

View File

@@ -52,7 +52,7 @@ class TestVersion(TestCase):
def test_copyright_up_to_date(self):
"""Copyright is current"""
code, out, err = self.t(("version",))
code, out, err = self.t("version")
expected = "Copyright \(C\) \d{4} - %d" % (datetime.now().year,)
self.assertRegexpMatches(out, expected)
@@ -70,7 +70,7 @@ class TestVersion(TestCase):
def test_version(self):
"""version command outputs expected version and license"""
code, out, err = self.t(("version",))
code, out, err = self.t("version")
expected = "task {0}".format(self.slurp())
self.assertIn(expected, out)
@@ -84,7 +84,7 @@ class TestVersion(TestCase):
def test_under_version(self):
"""_version outputs expected version and syntax"""
code, out, err = self.t(("_version",))
code, out, err = self.t("_version")
# version = "x.x.x (git-hash)" or simply "x.x.x"
# corresponding to "compiled from git" or "compiled from tarball"

View File

@@ -49,16 +49,16 @@ class TestWait(TestCase):
# [1] an hour before current time (visible 'now')
# [2] 22 hours after current time (hidden 'now', visible 'tomorrow')
self.t.faketime("-2h")
self.t(("add", "wait:1h", "visible"))
self.t(("add", "wait:1d", "hidden"))
self.t("add wait:1h visible")
self.t("add wait:1d hidden")
self.t.faketime()
code, out, err = self.t(("ls",))
code, out, err = self.t("ls")
self.assertIn("visible", out)
self.assertNotIn("hidden", out)
self.t.faketime("+1d")
code, out, err = self.t(("ls",))
code, out, err = self.t("ls")
self.assertIn("visible", out)
self.assertIn("hidden", out)
@@ -71,12 +71,12 @@ class TestBug434(TestCase):
def test_complete_waiting(self):
"""completion of waiting tasks"""
self.t(("add", "One", "wait:tomorrow"))
self.t("add One wait:tomorrow")
code, out, err = self.t(("1", "done"))
code, out, err = self.t("1 done")
self.assertIn("Completed 1 task", out)
code, out, err = self.t.runError(("ls",))
code, out, err = self.t.runError("ls")
self.assertNotIn("One", out)
self.assertIn("No matches", err)