package pttodo import ( "bytes" "encoding/json" "fmt" "os" "path" "strconv" "strings" "testing" "time" yaml "gopkg.in/yaml.v2" ) func TestJSONRoot(t *testing.T) { root := Root{ Todo: []Todo{Todo{Todo: "todo", Details: "detail", Schedule: "teehee", TS: 1}}, Scheduled: []Todo{Todo{Todo: "scheduled", Details: "detail", Schedule: "teehee", TS: 1}}, Done: []Todo{Todo{Todo: "done", Details: "detail", Schedule: "teehee", TS: 1}}, } var root2 Root if b, err := json.Marshal(root); err != nil { t.Fatal(err) } else if err := json.Unmarshal(b, &root2); err != nil { t.Fatal(err) } else if fmt.Sprint(root) != fmt.Sprint(root2) { t.Fatal(root, root2) } else if !root.Equals(root2) { t.Fatal(root2) } } func TestRootMoveScheduledToTodo(t *testing.T) { scheduleFuture := Schedule(strconv.FormatInt(time.Now().Unix()+100, 10)) schedulePast := Schedule(strconv.FormatInt(time.Now().Unix()-100, 10)) cases := map[string]struct { in Root want Root }{ "empty": {}, "no scheduled": { in: Root{Todo: []Todo{Todo{}}}, want: Root{Todo: []Todo{Todo{}}}, }, "one scheduled not ready": { in: Root{Scheduled: []Todo{Todo{Schedule: scheduleFuture}}}, want: Root{Scheduled: []Todo{Todo{Schedule: scheduleFuture}}}, }, "one scheduled ready": { in: Root{Scheduled: []Todo{Todo{Schedule: schedulePast}}}, want: Root{Todo: []Todo{Todo{Schedule: schedulePast}}}, }, "two scheduled one ready one not": { in: Root{ Scheduled: []Todo{ Todo{Schedule: schedulePast}, Todo{Schedule: scheduleFuture}, }, }, want: Root{ Todo: []Todo{ Todo{Schedule: schedulePast}, }, Scheduled: []Todo{ Todo{Schedule: scheduleFuture}, }, }, }, "two scheduled one not one ready": { in: Root{ Scheduled: []Todo{ Todo{Schedule: scheduleFuture}, Todo{Schedule: schedulePast}, }, }, want: Root{ Todo: []Todo{ Todo{Schedule: schedulePast}, }, Scheduled: []Todo{ Todo{Schedule: scheduleFuture}, }, }, }, } for name, d := range cases { c := d t.Run(name, func(t *testing.T) { inB, _ := json.Marshal(c.in) var got Root json.Unmarshal(inB, &got) wantB, _ := json.Marshal(c.want) var want Root json.Unmarshal(wantB, &want) got.MoveScheduledToTodo() if fmt.Sprintf("%+v", got) != fmt.Sprintf("%+v", want) { t.Fatalf("want \n\t%+v, got \n\t%+v", want, got) } else if !got.Equals(want) { t.Fatalf("want \n\t%+v, got \n\t%+v", want, got) } }) } } func TestMergeRoots(t *testing.T) { root0yaml := ` todo: - a - b - todo: c - todo: d tags: a - exclusive to 0 ` root1yaml := ` todo: - a - b - todo: c - todo: d tags: b - exclusive to 1 ` rootWantyaml := ` todo: - a - b - todo: c - todo: d tags: a - exclusive to 0 - exclusive to 1 ` var root0, root1, rootWant Root if err := yaml.Unmarshal([]byte(root0yaml), &root0); err != nil { t.Fatal(err) } if err := yaml.Unmarshal([]byte(root1yaml), &root1); err != nil { t.Fatal(err) } if err := yaml.Unmarshal([]byte(rootWantyaml), &rootWant); err != nil { t.Fatal(err) } root0.MergeIn(root1) if fmt.Sprintf("%+v", root0) != fmt.Sprintf("%+v", rootWant) { t.Fatalf("want \n\t%+v, got \n\t%+v", rootWant, root0) } else if !root0.Equals(rootWant) { t.Fatalf("want \n\t%+v, got \n\t%+v", rootWant, root0) } } func TestRootMarshalYAMLWriteTS(t *testing.T) { root := Root{ Todo: []Todo{Todo{Todo: "todo", TS: 1, writeTS: true}}, Scheduled: []Todo{Todo{Todo: "sched", TS: 2, writeTS: false, Schedule: "2099-01-01"}}, Done: []Todo{Todo{Todo: "done", TS: 3, writeTS: false}}, } got, err := yaml.Marshal(root) if err != nil { t.Fatal(err) } got = bytes.TrimSpace(got) want := strings.TrimSpace(` todo: - todo scheduled: - todo: sched schedule: "2099-01-01" ts: Wed Dec 31 17:00:02 MST 1969 done: - todo: done ts: Wed Dec 31 17:00:03 MST 1969 `) if string(got) != want { t.Fatalf("want\n\t%q, got\n\t%q", want, string(got)) } } func TestRootFromFile(t *testing.T) { cases := map[string]struct { given string want Root }{ "empty": {}, "happy": { given: `{"todo":["a", "b"],"scheduled":["c"], "done":[{"todo": "d"}]}`, want: Root{ Todo: []Todo{ Todo{Todo: "a"}, Todo{Todo: "b"}, }, Scheduled: []Todo{ Todo{Todo: "c"}, }, Done: []Todo{ Todo{Todo: "d"}, }, }, }, "todos": { given: `["a", {"todo": "b"}]`, want: Root{ Todo: []Todo{ {Todo: "a"}, {Todo: "b"}, }, }, }, } for name, d := range cases { c := d t.Run(name, func(t *testing.T) { d := t.TempDir() p := path.Join(d, "input.yaml") if err := os.WriteFile(p, []byte(c.given), os.ModePerm); err != nil { t.Fatal(err) } got, err := NewRootFromFile(p) if err != nil { t.Fatal(err) } if fmt.Sprintf("%+v", got) != fmt.Sprintf("%+v", c.want) { t.Errorf("want\n\t%+v, got\n\t%+v", c.want, got) } }) } } func TestRootFromFiles(t *testing.T) { d := t.TempDir() ps := []string{ path.Join(d, "a"), path.Join(d, "b"), } os.WriteFile(ps[0], []byte(`["a"]`), os.ModePerm) os.WriteFile(ps[1], []byte(`["b"]`), os.ModePerm) got, err := NewRootFromFiles(ps...) if err != nil { t.Fatal(err) } want := Root{ Todo: []Todo{ {Todo: "a"}, {Todo: "b"}, }, } if fmt.Sprintf("%+v", got) != fmt.Sprintf("%+v", want) { t.Errorf("want\n\t%+v, got \n\t%+v", want, got) } }