From caa944bb716f7d8d618d28afd30b0d7d892885a5 Mon Sep 17 00:00:00 2001 From: "jamesclonk@jamesclonk.ch" Date: Sat, 4 Jan 2014 01:43:27 +0100 Subject: [PATCH] finished implementing sort functions, plus overdue flag --- sort.go | 60 +-- sort_test.go | 305 ++++++++++++++ task.go | 25 ++ task_test.go | 415 ++++++++++++++++++ testdata/expected_todo.txt | 19 + testdata/ouput_todo.txt | 19 + testdata/sort_todo.txt | 28 ++ testdata/{input_todo.txt => task_todo.txt} | 12 +- testdata/tasklist_todo.txt | 63 +++ todotxt.go | 4 +- todotxt_test.go | 462 +-------------------- 11 files changed, 910 insertions(+), 502 deletions(-) create mode 100644 sort_test.go create mode 100644 task_test.go create mode 100644 testdata/sort_todo.txt rename testdata/{input_todo.txt => task_todo.txt} (89%) create mode 100644 testdata/tasklist_todo.txt diff --git a/sort.go b/sort.go index 7f84323..7fe975a 100644 --- a/sort.go +++ b/sort.go @@ -7,6 +7,7 @@ package todotxt import ( "errors" "sort" + "time" ) // Flags for defining sort element and order. @@ -36,7 +37,6 @@ func (tasklist *TaskList) Sort(sortFlag int) error { default: return errors.New("Unrecognized sort option") } - return nil } @@ -85,59 +85,39 @@ func (tasklist *TaskList) sortByPriority(order int) *TaskList { return tasklist } +func sortByDate(asc bool, hasDate1, hasDate2 bool, date1, date2 time.Time) bool { + if asc { // ASC + if hasDate1 && hasDate2 { + return date1.Before(date2) + } else { + return hasDate2 + } + } else { // DESC + if hasDate1 && hasDate2 { + return date1.After(date2) + } else { + return !hasDate2 + } + } +} + func (tasklist *TaskList) sortByCreatedDate(order int) *TaskList { tasklist.sortBy(func(t1, t2 *Task) bool { - if order == SORT_CREATED_DATE_DESC { // DESC - if t1.HasCreatedDate() && t2.HasCreatedDate() { - return t1.CreatedDate.After(t2.CreatedDate) - } else { - return !t1.HasCreatedDate() - } - } else { // ASC - if t1.HasCreatedDate() && t2.HasCreatedDate() { - return t1.CreatedDate.Before(t2.CreatedDate) - } else { - return t1.HasCreatedDate() - } - } + return sortByDate(order == SORT_CREATED_DATE_ASC, t1.HasCreatedDate(), t2.HasCreatedDate(), t1.CreatedDate, t2.CreatedDate) }) return tasklist } func (tasklist *TaskList) sortByCompletedDate(order int) *TaskList { tasklist.sortBy(func(t1, t2 *Task) bool { - if order == SORT_COMPLETED_DATE_DESC { // DESC - if t1.HasCompletedDate() && t2.HasCompletedDate() { - return t1.CompletedDate.After(t2.CompletedDate) - } else { - return !t1.HasCompletedDate() - } - } else { // ASC - if t1.HasCompletedDate() && t2.HasCompletedDate() { - return t1.CompletedDate.Before(t2.CompletedDate) - } else { - return t1.HasCompletedDate() - } - } + return sortByDate(order == SORT_COMPLETED_DATE_ASC, t1.HasCompletedDate(), t2.HasCompletedDate(), t1.CompletedDate, t2.CompletedDate) }) return tasklist } func (tasklist *TaskList) sortByDueDate(order int) *TaskList { tasklist.sortBy(func(t1, t2 *Task) bool { - if order == SORT_DUE_DATE_DESC { // DESC - if t1.HasDueDate() && t2.HasDueDate() { - return t1.DueDate.After(t2.DueDate) - } else { - return !t1.HasDueDate() - } - } else { // ASC - if t1.HasDueDate() && t2.HasDueDate() { - return t1.DueDate.Before(t2.DueDate) - } else { - return t1.HasDueDate() - } - } + return sortByDate(order == SORT_DUE_DATE_ASC, t1.HasDueDate(), t2.HasDueDate(), t1.DueDate, t2.DueDate) }) return tasklist } diff --git a/sort_test.go b/sort_test.go new file mode 100644 index 0000000..d678a91 --- /dev/null +++ b/sort_test.go @@ -0,0 +1,305 @@ +package todotxt + +import ( + "testing" +) + +var ( + testInputSort = "testdata/sort_todo.txt" +) + +func TestTaskSortByPriority(t *testing.T) { + testTasklist.LoadFromFilename(testInputSort) + taskId := 0 + + testTasklist = testTasklist[taskId : taskId+6] + + testTasklist.Sort(SORT_PRIORITY_ASC) + + testExpected = "(A) 2012-01-30 Call Mom @Call @Phone +Family" + testGot = testTasklist[0].Task() + if testGot != testExpected { + t.Errorf("Expected Task[1] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt" + testGot = testTasklist[1].Task() + if testGot != testExpected { + t.Errorf("Expected Task[2] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12" + testGot = testTasklist[2].Task() + if testGot != testExpected { + t.Errorf("Expected Task[3] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "(D) 2013-12-01 Outline chapter 5 @Computer +Novel Level:5 private:false due:2014-02-17" + testGot = testTasklist[3].Task() + if testGot != testExpected { + t.Errorf("Expected Task[4] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "2013-02-22 Pick up milk @GroceryStore" + testGot = testTasklist[4].Task() + if testGot != testExpected { + t.Errorf("Expected Task[5] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05" + testGot = testTasklist[5].Task() + if testGot != testExpected { + t.Errorf("Expected Task[6] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testTasklist.Sort(SORT_PRIORITY_DESC) + + testExpected = "x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05" + testGot = testTasklist[0].Task() + if testGot != testExpected { + t.Errorf("Expected Task[1] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "2013-02-22 Pick up milk @GroceryStore" + testGot = testTasklist[1].Task() + if testGot != testExpected { + t.Errorf("Expected Task[2] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "(D) 2013-12-01 Outline chapter 5 @Computer +Novel Level:5 private:false due:2014-02-17" + testGot = testTasklist[2].Task() + if testGot != testExpected { + t.Errorf("Expected Task[3] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12" + testGot = testTasklist[3].Task() + if testGot != testExpected { + t.Errorf("Expected Task[4] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt" + testGot = testTasklist[4].Task() + if testGot != testExpected { + t.Errorf("Expected Task[5] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "(A) 2012-01-30 Call Mom @Call @Phone +Family" + testGot = testTasklist[5].Task() + if testGot != testExpected { + t.Errorf("Expected Task[6] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } +} + +func TestTaskSortByCreatedDate(t *testing.T) { + testTasklist.LoadFromFilename(testInputSort) + taskId := 6 + + testTasklist = testTasklist[taskId : taskId+5] + + testTasklist.Sort(SORT_CREATED_DATE_ASC) + + testExpected = "x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05" + testGot = testTasklist[0].Task() + if testGot != testExpected { + t.Errorf("Expected Task[1] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "(A) Call Mom @Call @Phone +Family" + testGot = testTasklist[1].Task() + if testGot != testExpected { + t.Errorf("Expected Task[2] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "2013-02-22 Pick up milk @GroceryStore" + testGot = testTasklist[2].Task() + if testGot != testExpected { + t.Errorf("Expected Task[3] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt" + testGot = testTasklist[3].Task() + if testGot != testExpected { + t.Errorf("Expected Task[4] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12" + testGot = testTasklist[4].Task() + if testGot != testExpected { + t.Errorf("Expected Task[5] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testTasklist.Sort(SORT_CREATED_DATE_DESC) + + testExpected = "x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12" + testGot = testTasklist[0].Task() + if testGot != testExpected { + t.Errorf("Expected Task[1] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt" + testGot = testTasklist[1].Task() + if testGot != testExpected { + t.Errorf("Expected Task[2] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "2013-02-22 Pick up milk @GroceryStore" + testGot = testTasklist[2].Task() + if testGot != testExpected { + t.Errorf("Expected Task[3] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "(A) Call Mom @Call @Phone +Family" + testGot = testTasklist[3].Task() + if testGot != testExpected { + t.Errorf("Expected Task[4] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05" + testGot = testTasklist[4].Task() + if testGot != testExpected { + t.Errorf("Expected Task[5] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } +} + +func TestTaskSortByCompletedDate(t *testing.T) { + testTasklist.LoadFromFilename(testInputSort) + taskId := 11 + + testTasklist = testTasklist[taskId : taskId+6] + + testTasklist.Sort(SORT_COMPLETED_DATE_ASC) + + testExpected = "x Download Todo.txt mobile app @Phone" + testGot = testTasklist[0].Task() + if testGot != testExpected { + t.Errorf("Expected Task[1] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12" + testGot = testTasklist[1].Task() + if testGot != testExpected { + t.Errorf("Expected Task[2] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "2013-02-22 Pick up milk @GroceryStore" + testGot = testTasklist[2].Task() + if testGot != testExpected { + t.Errorf("Expected Task[3] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt" + testGot = testTasklist[3].Task() + if testGot != testExpected { + t.Errorf("Expected Task[4] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05" + testGot = testTasklist[4].Task() + if testGot != testExpected { + t.Errorf("Expected Task[5] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "x 2014-01-04 2014-01-01 Create some more golang library test cases @Go +go-todotxt" + testGot = testTasklist[5].Task() + if testGot != testExpected { + t.Errorf("Expected Task[6] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testTasklist.Sort(SORT_COMPLETED_DATE_DESC) + + testExpected = "x 2014-01-04 2014-01-01 Create some more golang library test cases @Go +go-todotxt" + testGot = testTasklist[0].Task() + if testGot != testExpected { + t.Errorf("Expected Task[1] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05" + testGot = testTasklist[1].Task() + if testGot != testExpected { + t.Errorf("Expected Task[2] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt" + testGot = testTasklist[2].Task() + if testGot != testExpected { + t.Errorf("Expected Task[3] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "2013-02-22 Pick up milk @GroceryStore" + testGot = testTasklist[3].Task() + if testGot != testExpected { + t.Errorf("Expected Task[4] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12" + testGot = testTasklist[4].Task() + if testGot != testExpected { + t.Errorf("Expected Task[5] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "x Download Todo.txt mobile app @Phone" + testGot = testTasklist[5].Task() + if testGot != testExpected { + t.Errorf("Expected Task[6] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } +} + +func TestTaskSortByDueDate(t *testing.T) { + testTasklist.LoadFromFilename(testInputSort) + taskId := 17 + + testTasklist = testTasklist[taskId : taskId+4] + + testTasklist.Sort(SORT_DUE_DATE_ASC) + + testExpected = "x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt" + testGot = testTasklist[0].Task() + if testGot != testExpected { + t.Errorf("Expected Task[1] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05" + testGot = testTasklist[1].Task() + if testGot != testExpected { + t.Errorf("Expected Task[2] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12" + testGot = testTasklist[2].Task() + if testGot != testExpected { + t.Errorf("Expected Task[3] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "(B) 2013-12-01 Outline chapter 5 @Computer +Novel Level:5 private:false due:2014-02-17" + testGot = testTasklist[3].Task() + if testGot != testExpected { + t.Errorf("Expected Task[4] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testTasklist.Sort(SORT_DUE_DATE_DESC) + + testExpected = "(B) 2013-12-01 Outline chapter 5 @Computer +Novel Level:5 private:false due:2014-02-17" + testGot = testTasklist[0].Task() + if testGot != testExpected { + t.Errorf("Expected Task[1] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12" + testGot = testTasklist[1].Task() + if testGot != testExpected { + t.Errorf("Expected Task[2] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05" + testGot = testTasklist[2].Task() + if testGot != testExpected { + t.Errorf("Expected Task[3] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } + + testExpected = "x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt" + testGot = testTasklist[3].Task() + if testGot != testExpected { + t.Errorf("Expected Task[4] after Sort() to be [%s], but got [%s]", testExpected, testGot) + } +} diff --git a/task.go b/task.go index 7b4ac16..727b060 100644 --- a/task.go +++ b/task.go @@ -108,3 +108,28 @@ func (task *Task) HasDueDate() bool { func (task *Task) HasCompletedDate() bool { return !task.CompletedDate.IsZero() } + +// IsOverdue returns true if due date is in the past. +// +// This function does not take the Completed flag into consideration. +// You should check Task.Completed first if needed. +func (task *Task) IsOverdue() bool { + if task.HasDueDate() { + return task.DueDate.Before(time.Now()) + } else { + return false + } +} + +// Due returns the duration passed since due date, or until due date from now. +// Check with IsOverdue() if the task is overdue or not. +// +// Just as with IsOverdue(), this function does also not take the Completed flag into consideration. +// You should check Task.Completed first if needed. +func (task *Task) Due() time.Duration { + if task.IsOverdue() { + return time.Now().Sub(task.DueDate) + } else { + return task.DueDate.Sub(time.Now()) + } +} diff --git a/task_test.go b/task_test.go new file mode 100644 index 0000000..e386983 --- /dev/null +++ b/task_test.go @@ -0,0 +1,415 @@ +package todotxt + +import ( + "testing" + "time" +) + +var ( + testInputTask = "testdata/task_todo.txt" +) + +func TestTaskString(t *testing.T) { + testTasklist.LoadFromFilename(testInputTask) + taskId := 1 + + testExpected = "2013-02-22 Pick up milk @GroceryStore" + testGot = testTasklist[taskId-1].String() + if testGot != testExpected { + t.Errorf("Expected Task[%d] to be [%s], but got [%s]", taskId, testExpected, testGot) + } + taskId++ + + testExpected = "x Download Todo.txt mobile app @Phone" + testGot = testTasklist[taskId-1].String() + if testGot != testExpected { + t.Errorf("Expected Task[%d] to be [%s], but got [%s]", taskId, testExpected, testGot) + } + taskId++ + + testExpected = "(B) 2013-12-01 Outline chapter 5 @Computer +Novel Level:5 private:false due:2014-02-17" + testGot = testTasklist[taskId-1].Task() + if testGot != testExpected { + t.Errorf("Expected Task[%d] to be [%s], but got [%s]", taskId, testExpected, testGot) + } + taskId++ + + testExpected = "x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt" + testGot = testTasklist[taskId-1].Task() + if testGot != testExpected { + t.Errorf("Expected Task[%d] to be [%s], but got [%s]", taskId, testExpected, testGot) + } + taskId++ + + testExpected = "x 2014-01-03 2014-01-01 Create some more golang library test cases @Go +go-todotxt" + testGot = testTasklist[taskId-1].Task() + if testGot != testExpected { + t.Errorf("Expected Task[%d] to be [%s], but got [%s]", taskId, testExpected, testGot) + } + taskId++ +} + +func TestTaskPriority(t *testing.T) { + testTasklist.LoadFromFilename(testInputTask) + taskId := 6 + + testExpected = "B" + testGot = testTasklist[taskId-1].Priority + if testGot != testExpected { + t.Errorf("Expected Task[%d] to have priority '%s', but got '%s'", taskId, testExpected, testGot) + } + taskId++ + + testExpected = "C" + testGot = testTasklist[taskId-1].Priority + if testGot != testExpected { + t.Errorf("Expected Task[%d] to have priority '%s', but got '%s'", taskId, testExpected, testGot) + } + taskId++ + + testExpected = "B" + testGot = testTasklist[taskId-1].Priority + if testGot != testExpected { + t.Errorf("Expected Task[%d] to have priority '%s', but got '%s'", taskId, testExpected, testGot) + } + taskId++ + + if testTasklist[taskId-1].HasPriority() { + t.Errorf("Expected Task[%d] to have no priority, but got '%s'", taskId, testTasklist[4].Priority) + } + taskId++ +} + +func TestTaskCreatedDate(t *testing.T) { + testTasklist.LoadFromFilename(testInputTask) + taskId := 10 + + testExpected, err := time.Parse(DateLayout, "2012-01-30") + if err != nil { + t.Fatal(err) + } + testGot = testTasklist[taskId-1].CreatedDate + if testGot != testExpected { + t.Errorf("Expected Task[%d] to have created date '%s', but got '%v'", taskId, testExpected, testGot) + } + taskId++ + + testExpected, err = time.Parse(DateLayout, "2013-02-22") + if err != nil { + t.Fatal(err) + } + testGot = testTasklist[taskId-1].CreatedDate + if testGot != testExpected { + t.Errorf("Expected Task[%d] to have created date '%s', but got '%v'", taskId, testExpected, testGot) + } + taskId++ + + testExpected, err = time.Parse(DateLayout, "2014-01-01") + if err != nil { + t.Fatal(err) + } + testGot = testTasklist[taskId-1].CreatedDate + if testGot != testExpected { + t.Errorf("Expected Task[%d] to have created date '%s', but got '%v'", taskId, testExpected, testGot) + } + taskId++ + + testExpected, err = time.Parse(DateLayout, "2013-12-30") + if err != nil { + t.Fatal(err) + } + testGot = testTasklist[taskId-1].CreatedDate + if testGot != testExpected { + t.Errorf("Expected Task[%d] to have created date '%s', but got '%v'", taskId, testExpected, testGot) + } + taskId++ + + testExpected, err = time.Parse(DateLayout, "2014-01-01") + if err != nil { + t.Fatal(err) + } + testGot = testTasklist[taskId-1].CreatedDate + if testGot != testExpected { + t.Errorf("Expected Task[%d] to have created date '%s', but got '%v'", taskId, testExpected, testGot) + } + taskId++ + + if testTasklist[taskId-1].HasCreatedDate() { + t.Errorf("Expected Task[%d] to have no created date, but got '%v'", taskId, testTasklist[4].CreatedDate) + } + taskId++ +} + +func TestTaskContexts(t *testing.T) { + testTasklist.LoadFromFilename(testInputTask) + taskId := 16 + + testExpected = []string{"Call", "Phone"} + testGot = testTasklist[taskId-1].Contexts + if !compareSlices(testGot.([]string), testExpected.([]string)) { + t.Errorf("Expected Task[%d] to have contexts '%v', but got '%v'", taskId, testExpected, testGot) + } + taskId++ + + testExpected = []string{"Office"} + testGot = testTasklist[taskId-1].Contexts + if !compareSlices(testGot.([]string), testExpected.([]string)) { + t.Errorf("Expected Task[%d] to have contexts '%v', but got '%v'", taskId, testExpected, testGot) + } + taskId++ + + testExpected = []string{"Electricity", "Home", "Of_Super-Importance", "Television"} + testGot = testTasklist[taskId-1].Contexts + if !compareSlices(testGot.([]string), testExpected.([]string)) { + t.Errorf("Expected Task[%d] to have contexts '%v', but got '%v'", taskId, testExpected, testGot) + } + taskId++ + + testExpected = []string{} + testGot = testTasklist[taskId-1].Contexts + if !compareSlices(testGot.([]string), testExpected.([]string)) { + t.Errorf("Expected Task[%d] to have no contexts, but got '%v'", taskId, testGot) + } + taskId++ +} + +func TestTasksProjects(t *testing.T) { + testTasklist.LoadFromFilename(testInputTask) + taskId := 20 + + testExpected = []string{"Gardening", "Improving", "Planning", "Relaxing-Work"} + testGot = testTasklist[taskId-1].Projects + if !compareSlices(testGot.([]string), testExpected.([]string)) { + t.Errorf("Expected Task[%d] to have projects '%v', but got '%v'", taskId, testExpected, testGot) + } + taskId++ + + testExpected = []string{"Novel"} + testGot = testTasklist[taskId-1].Projects + if !compareSlices(testGot.([]string), testExpected.([]string)) { + t.Errorf("Expected Task[%d] to have projects '%v', but got '%v'", taskId, testExpected, testGot) + } + taskId++ + + testExpected = []string{} + testGot = testTasklist[taskId-1].Projects + if !compareSlices(testGot.([]string), testExpected.([]string)) { + t.Errorf("Expected Task[%d] to have no projects, but got '%v'", taskId, testGot) + } + taskId++ +} + +func TestTaskDueDate(t *testing.T) { + testTasklist.LoadFromFilename(testInputTask) + taskId := 23 + + testExpected, err := time.Parse(DateLayout, "2014-02-17") + if err != nil { + t.Fatal(err) + } + testGot = testTasklist[taskId-1].DueDate + if testGot != testExpected { + t.Errorf("Expected Task[%d] to have due date '%s', but got '%v'", taskId, testExpected, testGot) + } + taskId++ + + if testTasklist[taskId-1].HasDueDate() { + t.Errorf("Expected Task[%d] to have no due date, but got '%v'", taskId, testTasklist[taskId-1].DueDate) + } + taskId++ +} + +func TestTaskAddonTags(t *testing.T) { + testTasklist.LoadFromFilename(testInputTask) + taskId := 25 + + testExpected = map[string]string{"Level": "5", "private": "false"} + testGot = testTasklist[taskId-1].AdditionalTags + if len(testGot.(map[string]string)) != 2 || + !compareMaps(testGot.(map[string]string), testExpected.(map[string]string)) { + t.Errorf("Expected Task[%d] to have addon tags '%v', but got '%v'", taskId, testExpected, testGot) + } + taskId++ + + testExpected = map[string]string{"Importance": "Very!"} + testGot = testTasklist[taskId-1].AdditionalTags + if len(testGot.(map[string]string)) != 1 || + !compareMaps(testGot.(map[string]string), testExpected.(map[string]string)) { + t.Errorf("Expected Task[%d] to have projects '%v', but got '%v'", taskId, testExpected, testGot) + } + taskId++ + + testExpected = map[string]string{} + testGot = testTasklist[taskId-1].AdditionalTags + if len(testGot.(map[string]string)) != 0 || + !compareMaps(testGot.(map[string]string), testExpected.(map[string]string)) { + t.Errorf("Expected Task[%d] to have no additional tags, but got '%v'", taskId, testGot) + } + taskId++ + + testExpected = map[string]string{} + testGot = testTasklist[taskId-1].AdditionalTags + if len(testGot.(map[string]string)) != 0 || + !compareMaps(testGot.(map[string]string), testExpected.(map[string]string)) { + t.Errorf("Expected Task[%d] to have no additional tags, but got '%v'", taskId, testGot) + } + taskId++ +} + +func TestTaskCompleted(t *testing.T) { + testTasklist.LoadFromFilename(testInputTask) + taskId := 29 + + testExpected = true + testGot = testTasklist[taskId-1].Completed + if testGot != testExpected { + t.Errorf("Expected Task[%d] not to be completed, but got '%v'", taskId, testGot) + } + taskId++ + + testExpected = true + testGot = testTasklist[taskId-1].Completed + if testGot != testExpected { + t.Errorf("Expected Task[%d] not to be completed, but got '%v'", taskId, testGot) + } + taskId++ + + testExpected = true + testGot = testTasklist[taskId-1].Completed + if testGot != testExpected { + t.Errorf("Expected Task[%d] not to be completed, but got '%v'", taskId, testGot) + } + taskId++ + + testExpected = false + testGot = testTasklist[taskId-1].Completed + if testGot != testExpected { + t.Errorf("Expected Task[%d] not to be completed, but got '%v'", taskId, testGot) + } + taskId++ + + testExpected = false + testGot = testTasklist[taskId-1].Completed + if testGot != testExpected { + t.Errorf("Expected Task[%d] not to be completed, but got '%v'", taskId, testGot) + } + taskId++ +} + +func TestTaskCompletedDate(t *testing.T) { + testTasklist.LoadFromFilename(testInputTask) + taskId := 34 + + if testTasklist[taskId-1].HasCompletedDate() { + t.Errorf("Expected Task[%d] to not have a completed date, but got '%v'", taskId, testTasklist[taskId-1].CompletedDate) + } + taskId++ + + testExpected, err := time.Parse(DateLayout, "2014-01-03") + if err != nil { + t.Fatal(err) + } + testGot = testTasklist[taskId-1].CompletedDate + if testGot != testExpected { + t.Errorf("Expected Task[%d] to have completed date '%s', but got '%v'", taskId, testExpected, testGot) + } + taskId++ + + if testTasklist[taskId-1].HasCompletedDate() { + t.Errorf("Expected Task[%d] to not have a completed date, but got '%v'", taskId, testTasklist[taskId-1].CompletedDate) + } + taskId++ + + testExpected, err = time.Parse(DateLayout, "2014-01-02") + if err != nil { + t.Fatal(err) + } + testGot = testTasklist[taskId-1].CompletedDate + if testGot != testExpected { + t.Errorf("Expected Task[%d] to have completed date '%s', but got '%v'", taskId, testExpected, testGot) + } + taskId++ + + testExpected, err = time.Parse(DateLayout, "2014-01-03") + if err != nil { + t.Fatal(err) + } + testGot = testTasklist[taskId-1].CompletedDate + if testGot != testExpected { + t.Errorf("Expected Task[%d] to have completed date '%s', but got '%v'", taskId, testExpected, testGot) + } + taskId++ + + if testTasklist[taskId-1].HasCompletedDate() { + t.Errorf("Expected Task[%d] to not have a completed date, but got '%v'", taskId, testTasklist[taskId-1].CompletedDate) + } + taskId++ +} + +func TestTaskIsOverdue(t *testing.T) { + testTasklist.LoadFromFilename(testInputTask) + taskId := 40 + + testGot = testTasklist[taskId-1].IsOverdue() + if !testGot.(bool) { + t.Errorf("Expected Task[%d] to be overdue, but got '%v'", taskId, testGot) + } + taskId++ + + testGot = testTasklist[taskId-1].IsOverdue() + if testGot.(bool) { + t.Errorf("Expected Task[%d] not to be overdue, but got '%v'", taskId, testGot) + } + testTasklist[taskId-1].DueDate = time.Now().AddDate(0, 0, 1) + testGot = testTasklist[taskId-1].Due() + if testGot.(time.Duration).Hours() < 23 || + testGot.(time.Duration).Hours() > 25 { + t.Errorf("Expected Task[%d] to be due in 24 hours, but got '%v'", taskId, testGot) + } + taskId++ + + testGot = testTasklist[taskId-1].IsOverdue() + if !testGot.(bool) { + t.Errorf("Expected Task[%d] to be overdue, but got '%v'", taskId, testGot) + } + testTasklist[taskId-1].DueDate = time.Now().AddDate(0, 0, -3) + testGot = testTasklist[taskId-1].Due() + if testGot.(time.Duration).Hours() < 71 || + testGot.(time.Duration).Hours() > 73 { + t.Errorf("Expected Task[%d] to be due since 72 hours, but got '%v'", taskId, testGot) + } + taskId++ +} + +func compareSlices(list1 []string, list2 []string) bool { + if len(list1) != len(list2) { + return false + } + + for i := range list1 { + if list1[i] != list2[i] { + return false + } + } + + return true +} + +func compareMaps(map1 map[string]string, map2 map[string]string) bool { + if len(map1) != len(map2) { + return false + } + + compare := func(map1 map[string]string, map2 map[string]string) bool { + for key, value := range map1 { + if value2, found := map2[key]; !found { + return false + } else if value != value2 { + return false + } + } + return true + } + + return compare(map1, map2) && compare(map2, map1) +} diff --git a/testdata/expected_todo.txt b/testdata/expected_todo.txt index e85dd5c..09dc6b1 100644 --- a/testdata/expected_todo.txt +++ b/testdata/expected_todo.txt @@ -9,6 +9,7 @@ x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt Plan backyard herb garden @Home +Gardening +Improving +Planning (A) 2012-01-30 Call Mom @Call @Phone +Family 2013-02-22 Pick up milk @GroceryStore +x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12 x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt x 2014-01-03 2014-01-01 Create some more golang library test cases @Go +go-todotxt (C) Add cover sheets @Office +TPSReports @@ -36,9 +37,27 @@ x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01 x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt x 2014-01-03 2014-01-01 Create some more golang library test cases @Go +go-todotxt 2013-02-22 Pick up milk @GroceryStore +x 2014-01-04 (B) 2013-12-30 Create golang library @Go +go-todotxt due:2014-01-02 +(B) 2013-12-01 Outline chapter 5 @Computer +Novel Level:5 private:false due:2014-02-17 +Research self-publishing services +Novel due:2014-01-01 2013-02-22 Pick up milk @GroceryStore x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12 (D) 2013-12-01 Outline chapter 5 @Computer +Novel Level:5 private:false due:2014-02-17 x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05 (A) 2012-01-30 Call Mom @Call @Phone +Family +x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt +x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05 +2013-02-22 Pick up milk @GroceryStore +(A) Call Mom @Call @Phone +Family +x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12 +x Download Todo.txt mobile app @Phone +x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05 +x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12 +x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt +x 2014-01-04 2014-01-01 Create some more golang library test cases @Go +go-todotxt +2013-02-22 Pick up milk @GroceryStore +(B) 2013-12-01 Outline chapter 5 @Computer +Novel Level:5 private:false due:2014-02-17 +x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt +x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05 +x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12 diff --git a/testdata/ouput_todo.txt b/testdata/ouput_todo.txt index e85dd5c..09dc6b1 100644 --- a/testdata/ouput_todo.txt +++ b/testdata/ouput_todo.txt @@ -9,6 +9,7 @@ x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt Plan backyard herb garden @Home +Gardening +Improving +Planning (A) 2012-01-30 Call Mom @Call @Phone +Family 2013-02-22 Pick up milk @GroceryStore +x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12 x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt x 2014-01-03 2014-01-01 Create some more golang library test cases @Go +go-todotxt (C) Add cover sheets @Office +TPSReports @@ -36,9 +37,27 @@ x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01 x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt x 2014-01-03 2014-01-01 Create some more golang library test cases @Go +go-todotxt 2013-02-22 Pick up milk @GroceryStore +x 2014-01-04 (B) 2013-12-30 Create golang library @Go +go-todotxt due:2014-01-02 +(B) 2013-12-01 Outline chapter 5 @Computer +Novel Level:5 private:false due:2014-02-17 +Research self-publishing services +Novel due:2014-01-01 2013-02-22 Pick up milk @GroceryStore x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12 (D) 2013-12-01 Outline chapter 5 @Computer +Novel Level:5 private:false due:2014-02-17 x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05 (A) 2012-01-30 Call Mom @Call @Phone +Family +x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt +x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05 +2013-02-22 Pick up milk @GroceryStore +(A) Call Mom @Call @Phone +Family +x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12 +x Download Todo.txt mobile app @Phone +x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05 +x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12 +x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt +x 2014-01-04 2014-01-01 Create some more golang library test cases @Go +go-todotxt +2013-02-22 Pick up milk @GroceryStore +(B) 2013-12-01 Outline chapter 5 @Computer +Novel Level:5 private:false due:2014-02-17 +x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt +x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05 +x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12 diff --git a/testdata/sort_todo.txt b/testdata/sort_todo.txt new file mode 100644 index 0000000..ddf6c28 --- /dev/null +++ b/testdata/sort_todo.txt @@ -0,0 +1,28 @@ +# Sort Priority test case +2013-02-22 Pick up milk @GroceryStore +x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt +x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12 +(D) 2013-12-01 private:false Outline chapter 5 +Novel @Computer Level:5 due:2014-02-17 +x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05 +(A) 2012-01-30 @Phone Call Mom @Call +Family + +# Sort CreatedDate test case +x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt +x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05 +2013-02-22 Pick up milk @GroceryStore +(A) @Phone Call Mom @Call +Family +x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12 + +# Sort CompletedDate test case +x Download Todo.txt mobile app @Phone +x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05 +x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12 +x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt +x 2014-01-04 2014-01-01 Create some more golang library test cases @Go +go-todotxt +2013-02-22 Pick up milk @GroceryStore + +# Sort DueDate test case +(B) 2013-12-01 private:false Outline chapter 5 +Novel @Computer due:2014-02-17 Level:5 +x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt +x 2014-01-03 due:2014-01-05 Create golang library @Go +go-todotxt +x (C) 2014-01-01 Create golang library documentation @Go due:2014-01-12 +go-todotxt diff --git a/testdata/input_todo.txt b/testdata/task_todo.txt similarity index 89% rename from testdata/input_todo.txt rename to testdata/task_todo.txt index f627162..c357f78 100644 --- a/testdata/input_todo.txt +++ b/testdata/task_todo.txt @@ -14,6 +14,7 @@ x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt # CreatedDate test cases (A) 2012-01-30 @Phone Call Mom @Call +Family 2013-02-22 Pick up milk @GroceryStore +x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12 x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt x 2014-01-03 2014-01-01 Create some more golang library test cases @Go +go-todotxt (C) Add cover sheets @Office +TPSReports @@ -54,10 +55,7 @@ x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt x 2014-01-03 2014-01-01 Create some more golang library test cases @Go +go-todotxt 2013-02-22 Pick up milk @GroceryStore -# Sort Priority test case -2013-02-22 Pick up milk @GroceryStore -x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt -x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12 -(D) 2013-12-01 private:false Outline chapter 5 +Novel @Computer Level:5 due:2014-02-17 -x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05 -(A) 2012-01-30 @Phone Call Mom @Call +Family +# Overdue test cases +x 2014-01-04 (B) 2013-12-30 Create golang library @Go +go-todotxt due:2014-01-02 +(B) 2013-12-01 private:false Outline chapter 5 +Novel @Computer due:2017-07-17 Level:5 +Research self-publishing services +Novel +Novel +Novel due:2014-01-01 diff --git a/testdata/tasklist_todo.txt b/testdata/tasklist_todo.txt new file mode 100644 index 0000000..804c225 --- /dev/null +++ b/testdata/tasklist_todo.txt @@ -0,0 +1,63 @@ +2013-02-22 Pick up milk @GroceryStore +x Download Todo.txt mobile app @Phone +(B) 2013-12-01 private:false Outline chapter 5 +Novel @Computer Level:5 due:2014-02-17 +x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt +x 2014-01-03 2014-01-01 Create some more golang library test cases @Go +go-todotxt +(B) 2013-12-01 private:false Outline chapter 5 +Novel @Computer Level:5 due:2014-02-17 +x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12 +x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt ++Gardening Plan backyard herb garden +Planning @Home +Improving +(A) 2012-01-30 @Phone Call Mom @Call +Family +2013-02-22 Pick up milk @GroceryStore +x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12 +x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt +x 2014-01-03 2014-01-01 Create some more golang library test cases @Go +go-todotxt +(C) Add cover sheets @Office +TPSReports +(A) 2012-01-30 @Phone Call Mom @Call +Family +(C) Add cover sheets @Office +TPSReports +@Home Turn off TV @Electricity @Television @Electricity @Of_Super-Importance Importance:Very! +Research self-publishing services +Novel +Novel +Novel due:2014-01-01 ++Gardening Plan backyard herb garden +Planning @Home +Improving +Relaxing-Work +Research self-publishing services +Novel +Novel +Novel due:2014-01-01 +@Home Turn off TV @Electricity @Television @Electricity Importance:Very! +(B) 2013-12-01 private:false Outline chapter 5 +Novel @Computer due:2014-02-17 Level:5 +x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt +(B) 2013-12-01 private:false Outline chapter 5 +Novel @Computer Level:5 due:2014-02-17 +@Home Turn off TV @Electricity @Television @Electricity Importance:Very! +x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12 +(A) 2012-01-30 @Phone Call Mom @Call +Family +x Create golang library @Go +go-todotxt due:2014-01-05 +x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05 +x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt +xylophone lesson +X 2012-01-01 Make resolutions +x Download Todo.txt mobile app @Phone +x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05 +x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12 +x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt +x 2014-01-03 2014-01-01 Create some more golang library test cases @Go +go-todotxt +2013-02-22 Pick up milk @GroceryStore +x 2014-01-04 (B) 2013-12-30 Create golang library @Go +go-todotxt due:2014-01-02 +(B) 2013-12-01 private:false Outline chapter 5 +Novel @Computer due:2014-02-17 Level:5 +Research self-publishing services +Novel +Novel +Novel due:2014-01-01 +2013-02-22 Pick up milk @GroceryStore +x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt +x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12 +(D) 2013-12-01 private:false Outline chapter 5 +Novel @Computer Level:5 due:2014-02-17 +x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05 +(A) 2012-01-30 @Phone Call Mom @Call +Family +x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt +x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05 +2013-02-22 Pick up milk @GroceryStore +(A) @Phone Call Mom @Call +Family +x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12 +x Download Todo.txt mobile app @Phone +x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05 +x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12 +x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt +x 2014-01-04 2014-01-01 Create some more golang library test cases @Go +go-todotxt +2013-02-22 Pick up milk @GroceryStore +(B) 2013-12-01 private:false Outline chapter 5 +Novel @Computer due:2014-02-17 Level:5 +x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt +x 2014-01-03 due:2014-01-05 Create golang library @Go +go-todotxt +x (C) 2014-01-01 Create golang library documentation @Go due:2014-01-12 +go-todotxt diff --git a/todotxt.go b/todotxt.go index d12f8ae..b74202b 100644 --- a/todotxt.go +++ b/todotxt.go @@ -33,8 +33,8 @@ var ( // unexported vars priorityRx = regexp.MustCompile(`^(x|x \d{4}-\d{2}-\d{2}|)\s*\(([A-Z])\)\s+`) // Match priority: '(A) ...' or 'x (A) ...' or 'x 2012-12-12 (A) ...' - // Match created date: '(A) 2012-12-12 ...' or 'x 2012-12-12 (A) 2012-12-12 ...' or 'x 2012-12-12 2012-12-12 ...' or '2012-12-12 ...' - createdDateRx = regexp.MustCompile(`^(\([A-Z]\)|x \d{4}-\d{2}-\d{2} \([A-Z]\)|x \d{4}-\d{2}-\d{2}|)\s*(\d{4}-\d{2}-\d{2})\s+`) + // Match created date: '(A) 2012-12-12 ...' or 'x 2012-12-12 (A) 2012-12-12 ...' or 'x (A) 2012-12-12 ...'or 'x 2012-12-12 2012-12-12 ...' or '2012-12-12 ...' + createdDateRx = regexp.MustCompile(`^(\([A-Z]\)|x \d{4}-\d{2}-\d{2} \([A-Z]\)|x \([A-Z]\)|x \d{4}-\d{2}-\d{2}|)\s*(\d{4}-\d{2}-\d{2})\s+`) completedRx = regexp.MustCompile(`^x\s+`) // Match completed: 'x ...' completedDateRx = regexp.MustCompile(`^x\s*(\d{4}-\d{2}-\d{2})\s+`) // Match completed date: 'x 2012-12-12 ...' addonTagRx = regexp.MustCompile(`(^|\s+)([\w-]+):(\S+)`) // Match additional tags date: '... due:2012-12-12 ...' diff --git a/todotxt_test.go b/todotxt_test.go index 2328fcb..e5d0254 100644 --- a/todotxt_test.go +++ b/todotxt_test.go @@ -8,11 +8,10 @@ import ( "io/ioutil" "os" "testing" - "time" ) var ( - testInput = "testdata/input_todo.txt" + testInputTasklist = "testdata/tasklist_todo.txt" testOutput = "testdata/ouput_todo.txt" testExpectedOutput = "testdata/expected_todo.txt" testTasklist TaskList @@ -21,7 +20,7 @@ var ( ) func TestLoadFromFile(t *testing.T) { - file, err := os.Open(testInput) + file, err := os.Open(testInputTasklist) if err != nil { t.Fatal(err) } @@ -43,7 +42,7 @@ func TestLoadFromFile(t *testing.T) { } func TestLoadFromFilename(t *testing.T) { - if testTasklist, err := LoadFromFilename(testInput); err != nil { + if testTasklist, err := LoadFromFilename(testInputTasklist); err != nil { t.Fatal(err) } else { data, err := ioutil.ReadFile(testExpectedOutput) @@ -63,7 +62,7 @@ func TestWriteFile(t *testing.T) { os.Create(testOutput) var err error - fileInput, err := os.Open(testInput) + fileInput, err := os.Open(testInputTasklist) if err != nil { t.Fatal(err) } @@ -105,7 +104,7 @@ func TestTaskListWriteFile(t *testing.T) { os.Create(testOutput) testTasklist := TaskList{} - fileInput, err := os.Open(testInput) + fileInput, err := os.Open(testInputTasklist) if err != nil { t.Fatal(err) } @@ -146,7 +145,7 @@ func TestWriteFilename(t *testing.T) { os.Remove(testOutput) var err error - if testTasklist, err = LoadFromFilename(testInput); err != nil { + if testTasklist, err = LoadFromFilename(testInputTasklist); err != nil { t.Fatal(err) } if err = WriteToFilename(&testTasklist, testOutput); err != nil { @@ -171,7 +170,7 @@ func TestTaskListWriteFilename(t *testing.T) { os.Remove(testOutput) testTasklist := TaskList{} - if err := testTasklist.LoadFromFilename(testInput); err != nil { + if err := testTasklist.LoadFromFilename(testInputTasklist); err != nil { t.Fatal(err) } if err := testTasklist.WriteToFilename(testOutput); err != nil { @@ -193,454 +192,11 @@ func TestTaskListWriteFilename(t *testing.T) { } func TestTaskListCount(t *testing.T) { - testTasklist.LoadFromFilename(testInput) + testTasklist.LoadFromFilename(testInputTasklist) - testExpected := 44 + testExpected := 63 testGot := len(testTasklist) if testGot != testExpected { t.Errorf("Expected TaskList to contain %d tasks, but got %d", testExpected, testGot) } } - -func TestTaskString(t *testing.T) { - testTasklist.LoadFromFilename(testInput) - taskId := 1 - - testExpected = "2013-02-22 Pick up milk @GroceryStore" - testGot = testTasklist[taskId-1].String() - if testGot != testExpected { - t.Errorf("Expected Task[%d] to be [%s], but got [%s]", taskId, testExpected, testGot) - } - taskId++ - - testExpected = "x Download Todo.txt mobile app @Phone" - testGot = testTasklist[taskId-1].String() - if testGot != testExpected { - t.Errorf("Expected Task[%d] to be [%s], but got [%s]", taskId, testExpected, testGot) - } - taskId++ - - testExpected = "(B) 2013-12-01 Outline chapter 5 @Computer +Novel Level:5 private:false due:2014-02-17" - testGot = testTasklist[taskId-1].Task() - if testGot != testExpected { - t.Errorf("Expected Task[%d] to be [%s], but got [%s]", taskId, testExpected, testGot) - } - taskId++ - - testExpected = "x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt" - testGot = testTasklist[taskId-1].Task() - if testGot != testExpected { - t.Errorf("Expected Task[%d] to be [%s], but got [%s]", taskId, testExpected, testGot) - } - taskId++ - - testExpected = "x 2014-01-03 2014-01-01 Create some more golang library test cases @Go +go-todotxt" - testGot = testTasklist[taskId-1].Task() - if testGot != testExpected { - t.Errorf("Expected Task[%d] to be [%s], but got [%s]", taskId, testExpected, testGot) - } - taskId++ -} - -func TestTaskPriority(t *testing.T) { - testTasklist.LoadFromFilename(testInput) - taskId := 6 - - testExpected = "B" - testGot = testTasklist[taskId-1].Priority - if testGot != testExpected { - t.Errorf("Expected Task[%d] to have priority '%s', but got '%s'", taskId, testExpected, testGot) - } - taskId++ - - testExpected = "C" - testGot = testTasklist[taskId-1].Priority - if testGot != testExpected { - t.Errorf("Expected Task[%d] to have priority '%s', but got '%s'", taskId, testExpected, testGot) - } - taskId++ - - testExpected = "B" - testGot = testTasklist[taskId-1].Priority - if testGot != testExpected { - t.Errorf("Expected Task[%d] to have priority '%s', but got '%s'", taskId, testExpected, testGot) - } - taskId++ - - if testTasklist[taskId-1].HasPriority() { - t.Errorf("Expected Task[%d] to have no priority, but got '%s'", taskId, testTasklist[4].Priority) - } - taskId++ -} - -func TestTaskCreatedDate(t *testing.T) { - testTasklist.LoadFromFilename(testInput) - taskId := 10 - - testExpected, err := time.Parse(DateLayout, "2012-01-30") - if err != nil { - t.Fatal(err) - } - testGot = testTasklist[taskId-1].CreatedDate - if testGot != testExpected { - t.Errorf("Expected Task[%d] to have created date '%s', but got '%v'", taskId, testExpected, testGot) - } - taskId++ - - testExpected, err = time.Parse(DateLayout, "2013-02-22") - if err != nil { - t.Fatal(err) - } - testGot = testTasklist[taskId-1].CreatedDate - if testGot != testExpected { - t.Errorf("Expected Task[%d] to have created date '%s', but got '%v'", taskId, testExpected, testGot) - } - taskId++ - - testExpected, err = time.Parse(DateLayout, "2013-12-30") - if err != nil { - t.Fatal(err) - } - testGot = testTasklist[taskId-1].CreatedDate - if testGot != testExpected { - t.Errorf("Expected Task[%d] to have created date '%s', but got '%v'", taskId, testExpected, testGot) - } - taskId++ - - testExpected, err = time.Parse(DateLayout, "2014-01-01") - if err != nil { - t.Fatal(err) - } - testGot = testTasklist[taskId-1].CreatedDate - if testGot != testExpected { - t.Errorf("Expected Task[%d] to have created date '%s', but got '%v'", taskId, testExpected, testGot) - } - taskId++ - - if testTasklist[taskId-1].HasCreatedDate() { - t.Errorf("Expected Task[%d] to have no created date, but got '%v'", taskId, testTasklist[4].CreatedDate) - } - taskId++ -} - -func TestTaskContexts(t *testing.T) { - testTasklist.LoadFromFilename(testInput) - taskId := 15 - - testExpected = []string{"Call", "Phone"} - testGot = testTasklist[taskId-1].Contexts - if !compareSlices(testGot.([]string), testExpected.([]string)) { - t.Errorf("Expected Task[%d] to have contexts '%v', but got '%v'", taskId, testExpected, testGot) - } - taskId++ - - testExpected = []string{"Office"} - testGot = testTasklist[taskId-1].Contexts - if !compareSlices(testGot.([]string), testExpected.([]string)) { - t.Errorf("Expected Task[%d] to have contexts '%v', but got '%v'", taskId, testExpected, testGot) - } - taskId++ - - testExpected = []string{"Electricity", "Home", "Of_Super-Importance", "Television"} - testGot = testTasklist[taskId-1].Contexts - if !compareSlices(testGot.([]string), testExpected.([]string)) { - t.Errorf("Expected Task[%d] to have contexts '%v', but got '%v'", taskId, testExpected, testGot) - } - taskId++ - - testExpected = []string{} - testGot = testTasklist[taskId-1].Contexts - if !compareSlices(testGot.([]string), testExpected.([]string)) { - t.Errorf("Expected Task[%d] to have no contexts, but got '%v'", taskId, testGot) - } - taskId++ -} - -func TestTasksProjects(t *testing.T) { - testTasklist.LoadFromFilename(testInput) - taskId := 19 - - testExpected = []string{"Gardening", "Improving", "Planning", "Relaxing-Work"} - testGot = testTasklist[taskId-1].Projects - if !compareSlices(testGot.([]string), testExpected.([]string)) { - t.Errorf("Expected Task[%d] to have projects '%v', but got '%v'", taskId, testExpected, testGot) - } - taskId++ - - testExpected = []string{"Novel"} - testGot = testTasklist[taskId-1].Projects - if !compareSlices(testGot.([]string), testExpected.([]string)) { - t.Errorf("Expected Task[%d] to have projects '%v', but got '%v'", taskId, testExpected, testGot) - } - taskId++ - - testExpected = []string{} - testGot = testTasklist[taskId-1].Projects - if !compareSlices(testGot.([]string), testExpected.([]string)) { - t.Errorf("Expected Task[%d] to have no projects, but got '%v'", taskId, testGot) - } - taskId++ -} - -func TestTaskDueDate(t *testing.T) { - testTasklist.LoadFromFilename(testInput) - taskId := 22 - - testExpected, err := time.Parse(DateLayout, "2014-02-17") - if err != nil { - t.Fatal(err) - } - testGot = testTasklist[taskId-1].DueDate - if testGot != testExpected { - t.Errorf("Expected Task[%d] to have due date '%s', but got '%v'", taskId, testExpected, testGot) - } - taskId++ - - if testTasklist[taskId-1].HasDueDate() { - t.Errorf("Expected Task[%d] to have no due date, but got '%v'", taskId, testTasklist[taskId-1].DueDate) - } - taskId++ -} - -func TestTaskAddonTags(t *testing.T) { - testTasklist.LoadFromFilename(testInput) - taskId := 24 - - testExpected = map[string]string{"Level": "5", "private": "false"} - testGot = testTasklist[taskId-1].AdditionalTags - if len(testGot.(map[string]string)) != 2 || - !compareMaps(testGot.(map[string]string), testExpected.(map[string]string)) { - t.Errorf("Expected Task[%d] to have addon tags '%v', but got '%v'", taskId, testExpected, testGot) - } - taskId++ - - testExpected = map[string]string{"Importance": "Very!"} - testGot = testTasklist[taskId-1].AdditionalTags - if len(testGot.(map[string]string)) != 1 || - !compareMaps(testGot.(map[string]string), testExpected.(map[string]string)) { - t.Errorf("Expected Task[%d] to have projects '%v', but got '%v'", taskId, testExpected, testGot) - } - taskId++ - - testExpected = map[string]string{} - testGot = testTasklist[taskId-1].AdditionalTags - if len(testGot.(map[string]string)) != 0 || - !compareMaps(testGot.(map[string]string), testExpected.(map[string]string)) { - t.Errorf("Expected Task[%d] to have no additional tags, but got '%v'", taskId, testGot) - } - taskId++ - - testExpected = map[string]string{} - testGot = testTasklist[taskId-1].AdditionalTags - if len(testGot.(map[string]string)) != 0 || - !compareMaps(testGot.(map[string]string), testExpected.(map[string]string)) { - t.Errorf("Expected Task[%d] to have no additional tags, but got '%v'", taskId, testGot) - } - taskId++ -} - -func TestTaskCompleted(t *testing.T) { - testTasklist.LoadFromFilename(testInput) - taskId := 28 - - testExpected = true - testGot = testTasklist[taskId-1].Completed - if testGot != testExpected { - t.Errorf("Expected Task[%d] not to completed, but got '%v'", taskId, testGot) - } - taskId++ - - testExpected = true - testGot = testTasklist[taskId-1].Completed - if testGot != testExpected { - t.Errorf("Expected Task[%d] not to completed, but got '%v'", taskId, testGot) - } - taskId++ - - testExpected = true - testGot = testTasklist[taskId-1].Completed - if testGot != testExpected { - t.Errorf("Expected Task[%d] not to completed, but got '%v'", taskId, testGot) - } - taskId++ - - testExpected = false - testGot = testTasklist[taskId-1].Completed - if testGot != testExpected { - t.Errorf("Expected Task[%d] not to be completed, but got '%v'", taskId, testGot) - } - taskId++ - - testExpected = false - testGot = testTasklist[taskId-1].Completed - if testGot != testExpected { - t.Errorf("Expected Task[%d] not to be completed, but got '%v'", taskId, testGot) - } - taskId++ -} - -func TestTaskCompletedDate(t *testing.T) { - testTasklist.LoadFromFilename(testInput) - taskId := 33 - - if testTasklist[taskId-1].HasCompletedDate() { - t.Errorf("Expected Task[%d] to not have a completed date, but got '%v'", taskId, testTasklist[taskId-1].CompletedDate) - } - taskId++ - - testExpected, err := time.Parse(DateLayout, "2014-01-03") - if err != nil { - t.Fatal(err) - } - testGot = testTasklist[taskId-1].CompletedDate - if testGot != testExpected { - t.Errorf("Expected Task[%d] to have completed date '%s', but got '%v'", taskId, testExpected, testGot) - } - taskId++ - - if testTasklist[taskId-1].HasCompletedDate() { - t.Errorf("Expected Task[%d] to not have a completed date, but got '%v'", taskId, testTasklist[taskId-1].CompletedDate) - } - taskId++ - - testExpected, err = time.Parse(DateLayout, "2014-01-02") - if err != nil { - t.Fatal(err) - } - testGot = testTasklist[taskId-1].CompletedDate - if testGot != testExpected { - t.Errorf("Expected Task[%d] to have completed date '%s', but got '%v'", taskId, testExpected, testGot) - } - taskId++ - - testExpected, err = time.Parse(DateLayout, "2014-01-03") - if err != nil { - t.Fatal(err) - } - testGot = testTasklist[taskId-1].CompletedDate - if testGot != testExpected { - t.Errorf("Expected Task[%d] to have completed date '%s', but got '%v'", taskId, testExpected, testGot) - } - taskId++ - - if testTasklist[taskId-1].HasCompletedDate() { - t.Errorf("Expected Task[%d] to not have a completed date, but got '%v'", taskId, testTasklist[taskId-1].CompletedDate) - } - taskId++ -} - -func TestTaskSortByPriority(t *testing.T) { - testTasklist.LoadFromFilename(testInput) - taskId := 38 - - testTasklist = testTasklist[taskId:] - - testTasklist.Sort(SORT_PRIORITY_ASC) - - testExpected = "(A) 2012-01-30 Call Mom @Call @Phone +Family" - testGot = testTasklist[0].Task() - if testGot != testExpected { - t.Errorf("Expected Task[1] after Sort() to be [%s], but got [%s]", testExpected, testGot) - } - - testExpected = "x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt" - testGot = testTasklist[1].Task() - if testGot != testExpected { - t.Errorf("Expected Task[2] after Sort() to be [%s], but got [%s]", testExpected, testGot) - } - - testExpected = "x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12" - testGot = testTasklist[2].Task() - if testGot != testExpected { - t.Errorf("Expected Task[3] after Sort() to be [%s], but got [%s]", testExpected, testGot) - } - - testExpected = "(D) 2013-12-01 Outline chapter 5 @Computer +Novel Level:5 private:false due:2014-02-17" - testGot = testTasklist[3].Task() - if testGot != testExpected { - t.Errorf("Expected Task[4] after Sort() to be [%s], but got [%s]", testExpected, testGot) - } - - testExpected = "2013-02-22 Pick up milk @GroceryStore" - testGot = testTasklist[4].Task() - if testGot != testExpected { - t.Errorf("Expected Task[5] after Sort() to be [%s], but got [%s]", testExpected, testGot) - } - - testExpected = "x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05" - testGot = testTasklist[5].Task() - if testGot != testExpected { - t.Errorf("Expected Task[6] after Sort() to be [%s], but got [%s]", testExpected, testGot) - } - - testTasklist.Sort(SORT_PRIORITY_DESC) - - testExpected = "x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05" - testGot = testTasklist[0].Task() - if testGot != testExpected { - t.Errorf("Expected Task[1] after Sort() to be [%s], but got [%s]", testExpected, testGot) - } - - testExpected = "2013-02-22 Pick up milk @GroceryStore" - testGot = testTasklist[1].Task() - if testGot != testExpected { - t.Errorf("Expected Task[2] after Sort() to be [%s], but got [%s]", testExpected, testGot) - } - - testExpected = "(D) 2013-12-01 Outline chapter 5 @Computer +Novel Level:5 private:false due:2014-02-17" - testGot = testTasklist[2].Task() - if testGot != testExpected { - t.Errorf("Expected Task[3] after Sort() to be [%s], but got [%s]", testExpected, testGot) - } - - testExpected = "x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12" - testGot = testTasklist[3].Task() - if testGot != testExpected { - t.Errorf("Expected Task[4] after Sort() to be [%s], but got [%s]", testExpected, testGot) - } - - testExpected = "x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt" - testGot = testTasklist[4].Task() - if testGot != testExpected { - t.Errorf("Expected Task[5] after Sort() to be [%s], but got [%s]", testExpected, testGot) - } - - testExpected = "(A) 2012-01-30 Call Mom @Call @Phone +Family" - testGot = testTasklist[5].Task() - if testGot != testExpected { - t.Errorf("Expected Task[6] after Sort() to be [%s], but got [%s]", testExpected, testGot) - } -} - -func compareSlices(list1 []string, list2 []string) bool { - if len(list1) != len(list2) { - return false - } - - for i := range list1 { - if list1[i] != list2[i] { - return false - } - } - - return true -} - -func compareMaps(map1 map[string]string, map2 map[string]string) bool { - if len(map1) != len(map2) { - return false - } - - compare := func(map1 map[string]string, map2 map[string]string) bool { - for key, value := range map1 { - if value2, found := map2[key]; !found { - return false - } else if value != value2 { - return false - } - } - return true - } - - return compare(map1, map2) && compare(map2, map1) -}