cli + tui to publish to leaflet (wip) & manage tasks, notes & watch/read lists 馃崈
charm
leaflet
readability
golang
1package main
2
3import (
4 "context"
5 "os"
6 "slices"
7 "strings"
8 "testing"
9
10 "github.com/stormlightlabs/noteleaf/internal/handlers"
11 "github.com/stormlightlabs/noteleaf/internal/services"
12)
13
14func setupCommandTest(t *testing.T) func() {
15 tempDir, err := os.MkdirTemp("", "noteleaf-cmd-test-*")
16 if err != nil {
17 t.Fatalf("Failed to create temp dir: %v", err)
18 }
19
20 oldConfigHome := os.Getenv("XDG_CONFIG_HOME")
21 os.Setenv("XDG_CONFIG_HOME", tempDir)
22
23 cleanup := func() {
24 os.Setenv("XDG_CONFIG_HOME", oldConfigHome)
25 os.RemoveAll(tempDir)
26 }
27
28 ctx := context.Background()
29 err = handlers.Setup(ctx, []string{})
30 if err != nil {
31 cleanup()
32 t.Fatalf("Failed to setup database: %v", err)
33 }
34
35 return cleanup
36}
37
38func createTestTaskHandler(t *testing.T) (*handlers.TaskHandler, func()) {
39 cleanup := setupCommandTest(t)
40 handler, err := handlers.NewTaskHandler()
41 if err != nil {
42 cleanup()
43 t.Fatalf("Failed to create test task handler: %v", err)
44 }
45 return handler, func() {
46 handler.Close()
47 cleanup()
48 }
49}
50
51func createTestMovieHandler(t *testing.T) (*handlers.MovieHandler, func()) {
52 cleanup := setupCommandTest(t)
53 handler, err := handlers.NewMovieHandler()
54 if err != nil {
55 cleanup()
56 t.Fatalf("Failed to create test movie handler: %v", err)
57 }
58 return handler, func() {
59 handler.Close()
60 cleanup()
61 }
62}
63
64func createTestTVHandler(t *testing.T) (*handlers.TVHandler, func()) {
65 cleanup := setupCommandTest(t)
66 handler, err := handlers.NewTVHandler()
67 if err != nil {
68 cleanup()
69 t.Fatalf("Failed to create test TV handler: %v", err)
70 }
71 return handler, func() {
72 handler.Close()
73 cleanup()
74 }
75}
76
77func createTestNoteHandler(t *testing.T) (*handlers.NoteHandler, func()) {
78 cleanup := setupCommandTest(t)
79 handler, err := handlers.NewNoteHandler()
80 if err != nil {
81 cleanup()
82 t.Fatalf("Failed to create test note handler: %v", err)
83 }
84 return handler, func() {
85 handler.Close()
86 cleanup()
87 }
88}
89
90func createTestBookHandler(t *testing.T) (*handlers.BookHandler, func()) {
91 cleanup := setupCommandTest(t)
92 handler, err := handlers.NewBookHandler()
93 if err != nil {
94 cleanup()
95 t.Fatalf("Failed to create test book handler: %v", err)
96 }
97 return handler, func() {
98 handler.Close()
99 cleanup()
100 }
101}
102
103func createTestArticleHandler(t *testing.T) (*handlers.ArticleHandler, func()) {
104 cleanup := setupCommandTest(t)
105 handler, err := handlers.NewArticleHandler()
106 if err != nil {
107 cleanup()
108 t.Fatalf("Failed to create test article handler: %v", err)
109 }
110 return handler, func() {
111 handler.Close()
112 cleanup()
113 }
114}
115
116func findSubcommand(commands []string, target string) bool {
117 return slices.Contains(commands, target)
118}
119
120func TestCommandGroup(t *testing.T) {
121 t.Run("Interface Implementations", func(t *testing.T) {
122 taskHandler, taskCleanup := createTestTaskHandler(t)
123 defer taskCleanup()
124
125 movieHandler, movieCleanup := createTestMovieHandler(t)
126 defer movieCleanup()
127
128 tvHandler, tvCleanup := createTestTVHandler(t)
129 defer tvCleanup()
130
131 noteHandler, noteCleanup := createTestNoteHandler(t)
132 defer noteCleanup()
133
134 bookHandler, bookCleanup := createTestBookHandler(t)
135 defer bookCleanup()
136
137 articleHandler, articleCleanup := createTestArticleHandler(t)
138 defer articleCleanup()
139
140 var _ CommandGroup = NewTaskCommand(taskHandler)
141 var _ CommandGroup = NewMovieCommand(movieHandler)
142 var _ CommandGroup = NewTVCommand(tvHandler)
143 var _ CommandGroup = NewNoteCommand(noteHandler)
144 var _ CommandGroup = NewBookCommand(bookHandler)
145 var _ CommandGroup = NewArticleCommand(articleHandler)
146 })
147
148 t.Run("Create", func(t *testing.T) {
149 t.Run("TaskCommand", func(t *testing.T) {
150 handler, cleanup := createTestTaskHandler(t)
151 defer cleanup()
152
153 commands := NewTaskCommand(handler)
154 cmd := commands.Create()
155
156 if cmd == nil {
157 t.Fatal("Create returned nil")
158 }
159 if cmd.Use != "todo" {
160 t.Errorf("Expected Use to be 'todo', got '%s'", cmd.Use)
161 }
162 if len(cmd.Aliases) != 1 || cmd.Aliases[0] != "task" {
163 t.Errorf("Expected aliases to be ['task'], got %v", cmd.Aliases)
164 }
165 if cmd.Short != "task management" {
166 t.Errorf("Expected Short to be 'task management', got '%s'", cmd.Short)
167 }
168 if !cmd.HasSubCommands() {
169 t.Error("Expected command to have subcommands")
170 }
171 })
172
173 t.Run("MovieCommand", func(t *testing.T) {
174 handler, cleanup := createTestMovieHandler(t)
175 defer cleanup()
176
177 commands := NewMovieCommand(handler)
178 cmd := commands.Create()
179
180 if cmd == nil {
181 t.Fatal("Create returned nil")
182 }
183 if cmd.Use != "movie" {
184 t.Errorf("Expected Use to be 'movie', got '%s'", cmd.Use)
185 }
186 if cmd.Short != "Manage movie watch queue" {
187 t.Errorf("Expected Short to be 'Manage movie watch queue', got '%s'", cmd.Short)
188 }
189 if !cmd.HasSubCommands() {
190 t.Error("Expected command to have subcommands")
191 }
192
193 subcommands := cmd.Commands()
194 subcommandNames := make([]string, len(subcommands))
195 for i, subcmd := range subcommands {
196 subcommandNames[i] = subcmd.Use
197 }
198
199 expectedSubcommands := []string{
200 "add [search query...]",
201 "list [--all|--watched|--queued]",
202 "watched [id]",
203 "remove [id]",
204 }
205
206 for _, expected := range expectedSubcommands {
207 if !findSubcommand(subcommandNames, expected) {
208 t.Errorf("Expected subcommand '%s' not found in %v", expected, subcommandNames)
209 }
210 }
211 })
212
213 t.Run("TVCommand", func(t *testing.T) {
214 handler, cleanup := createTestTVHandler(t)
215 defer cleanup()
216
217 commands := NewTVCommand(handler)
218 cmd := commands.Create()
219
220 if cmd == nil {
221 t.Fatal("Create returned nil")
222 }
223 if cmd.Use != "tv" {
224 t.Errorf("Expected Use to be 'tv', got '%s'", cmd.Use)
225 }
226 if cmd.Short != "Manage TV show watch queue" {
227 t.Errorf("Expected Short to be 'Manage TV show watch queue', got '%s'", cmd.Short)
228 }
229 if !cmd.HasSubCommands() {
230 t.Error("Expected command to have subcommands")
231 }
232
233 subcommands := cmd.Commands()
234 subcommandNames := make([]string, len(subcommands))
235 for i, subcmd := range subcommands {
236 subcommandNames[i] = subcmd.Use
237 }
238
239 expectedSubcommands := []string{
240 "add [search query...]",
241 "list [--all|--queued|--watching|--watched]",
242 "watching [id]",
243 "watched [id]",
244 "remove [id]",
245 }
246
247 for _, expected := range expectedSubcommands {
248 if !findSubcommand(subcommandNames, expected) {
249 t.Errorf("Expected subcommand '%s' not found in %v", expected, subcommandNames)
250 }
251 }
252 })
253
254 t.Run("NoteCommand", func(t *testing.T) {
255 handler, cleanup := createTestNoteHandler(t)
256 defer cleanup()
257
258 commands := NewNoteCommand(handler)
259 cmd := commands.Create()
260
261 if cmd == nil {
262 t.Fatal("Create returned nil")
263 }
264 if cmd.Use != "note" {
265 t.Errorf("Expected Use to be 'note', got '%s'", cmd.Use)
266 }
267 if cmd.Short != "Manage notes" {
268 t.Errorf("Expected Short to be 'Manage notes', got '%s'", cmd.Short)
269 }
270 if !cmd.HasSubCommands() {
271 t.Error("Expected command to have subcommands")
272 }
273
274 subcommands := cmd.Commands()
275 subcommandNames := make([]string, len(subcommands))
276 for i, subcmd := range subcommands {
277 subcommandNames[i] = subcmd.Use
278 }
279
280 expectedSubcommands := []string{
281 "create [title] [content...]",
282 "list [--archived] [--static] [--tags=tag1,tag2]",
283 "read [note-id]",
284 "edit [note-id]",
285 "remove [note-id]",
286 }
287
288 for _, expected := range expectedSubcommands {
289 if !findSubcommand(subcommandNames, expected) {
290 t.Errorf("Expected subcommand '%s' not found in %v", expected, subcommandNames)
291 }
292 }
293 })
294
295 t.Run("BookCommand", func(t *testing.T) {
296 handler, cleanup := createTestBookHandler(t)
297 defer cleanup()
298
299 commands := NewBookCommand(handler)
300 cmd := commands.Create()
301
302 if cmd == nil {
303 t.Fatal("Create returned nil")
304 }
305 if cmd.Use != "book" {
306 t.Errorf("Expected Use to be 'book', got '%s'", cmd.Use)
307 }
308 if cmd.Short != "Manage reading list" {
309 t.Errorf("Expected Short to be 'Manage reading list', got '%s'", cmd.Short)
310 }
311 if !cmd.HasSubCommands() {
312 t.Error("Expected command to have subcommands")
313 }
314
315 subcommands := cmd.Commands()
316 subcommandNames := make([]string, len(subcommands))
317 for i, subcmd := range subcommands {
318 subcommandNames[i] = subcmd.Use
319 }
320
321 expectedSubcommands := []string{
322 "add [search query...]",
323 "list [--all|--reading|--finished|--queued]",
324 "reading <id>",
325 "finished <id>",
326 "remove <id>",
327 "progress <id> <percentage>",
328 "update <id> <status>",
329 }
330
331 for _, expected := range expectedSubcommands {
332 if !findSubcommand(subcommandNames, expected) {
333 t.Errorf("Expected subcommand '%s' not found in %v", expected, subcommandNames)
334 }
335 }
336 })
337
338 t.Run("ArticleCommand", func(t *testing.T) {
339 handler, cleanup := createTestArticleHandler(t)
340 defer cleanup()
341
342 commands := NewArticleCommand(handler)
343 cmd := commands.Create()
344
345 if cmd == nil {
346 t.Fatal("Create returned nil")
347 }
348 if cmd.Use != "article" {
349 t.Errorf("Expected Use to be 'article', got '%s'", cmd.Use)
350 }
351 if cmd.Short != "Manage saved articles" {
352 t.Errorf("Expected Short to be 'Manage saved articles', got '%s'", cmd.Short)
353 }
354 if !cmd.HasSubCommands() {
355 t.Error("Expected command to have subcommands")
356 }
357
358 subcommands := cmd.Commands()
359 subcommandNames := make([]string, len(subcommands))
360 for i, subcmd := range subcommands {
361 subcommandNames[i] = subcmd.Use
362 }
363
364 for _, expected := range []string{"add <url>", "list [query]", "view <id>", "remove <id>"} {
365 if !findSubcommand(subcommandNames, expected) {
366 t.Errorf("Expected subcommand '%s' not found in %v", expected, subcommandNames)
367 }
368 }
369 })
370
371 t.Run("all command groups implement Create", func(t *testing.T) {
372 taskHandler, taskCleanup := createTestTaskHandler(t)
373 defer taskCleanup()
374
375 movieHandler, movieCleanup := createTestMovieHandler(t)
376 defer movieCleanup()
377
378 tvHandler, tvCleanup := createTestTVHandler(t)
379 defer tvCleanup()
380
381 noteHandler, noteCleanup := createTestNoteHandler(t)
382 defer noteCleanup()
383
384 bookHandler, bookCleanup := createTestBookHandler(t)
385 defer bookCleanup()
386
387 articleHandler, articleCleanup := createTestArticleHandler(t)
388 defer articleCleanup()
389
390 groups := []CommandGroup{
391 NewTaskCommand(taskHandler),
392 NewMovieCommand(movieHandler),
393 NewTVCommand(tvHandler),
394 NewNoteCommand(noteHandler),
395 NewBookCommand(bookHandler),
396 NewArticleCommand(articleHandler),
397 }
398
399 for i, group := range groups {
400 cmd := group.Create()
401 if cmd == nil {
402 t.Errorf("CommandGroup %d returned nil from Create()", i)
403 continue
404 }
405 if cmd.Use == "" {
406 t.Errorf("CommandGroup %d returned command with empty Use", i)
407 }
408 }
409 })
410 })
411
412}
413
414func TestCommandExecution(t *testing.T) {
415 t.Run("Movie Commands", func(t *testing.T) {
416 handler, cleanup := createTestMovieHandler(t)
417 defer cleanup()
418
419 t.Run("list command - default", func(t *testing.T) {
420 cmd := NewMovieCommand(handler).Create()
421 cmd.SetArgs([]string{"list"})
422 err := cmd.Execute()
423 if err != nil {
424 t.Errorf("movie list command failed: %v", err)
425 }
426 })
427
428 t.Run("add command with empty args", func(t *testing.T) {
429 cmd := NewMovieCommand(handler).Create()
430 cmd.SetArgs([]string{"add"})
431 err := cmd.Execute()
432 if err == nil {
433 t.Error("expected movie add command to fail with empty args")
434 }
435 })
436
437 t.Run("add command with valid args - successful search", func(t *testing.T) {
438 cleanup := services.SetupSuccessfulMovieMocks(t)
439 defer cleanup()
440
441 cmd := NewMovieCommand(handler).Create()
442 cmd.SetArgs([]string{"add", "Fantastic Four"})
443 err := cmd.Execute()
444
445 // NOTE: The command will find results but fail due to no user input in test environment
446 if err == nil {
447 t.Error("expected movie add command to fail due to no user input in test environment")
448 }
449 if !strings.Contains(err.Error(), "invalid input") {
450 t.Errorf("expected 'invalid input' error, got: %v", err)
451 }
452 })
453
454 t.Run("add command with valid args - search failure", func(t *testing.T) {
455 cleanup := services.SetupFailureMocks(t, "search failed")
456 defer cleanup()
457
458 cmd := NewMovieCommand(handler).Create()
459 cmd.SetArgs([]string{"add", "some movie"})
460 err := cmd.Execute()
461 if err == nil {
462 t.Error("expected movie add command to fail when search fails")
463 }
464 services.AssertErrorContains(t, err, "search failed")
465 })
466
467 t.Run("remove command with non-existent movie ID", func(t *testing.T) {
468 cmd := NewMovieCommand(handler).Create()
469 cmd.SetArgs([]string{"remove", "999"})
470 err := cmd.Execute()
471 if err == nil {
472 t.Error("expected movie remove command to fail with non-existent ID")
473 }
474 })
475
476 t.Run("remove command with non-numeric ID", func(t *testing.T) {
477 cmd := NewMovieCommand(handler).Create()
478 cmd.SetArgs([]string{"remove", "invalid"})
479 err := cmd.Execute()
480 if err == nil {
481 t.Error("expected movie remove command to fail with non-numeric ID")
482 }
483 })
484 })
485
486 t.Run("TV Commands", func(t *testing.T) {
487 handler, cleanup := createTestTVHandler(t)
488 defer cleanup()
489
490 t.Run("list command - default", func(t *testing.T) {
491 cmd := NewTVCommand(handler).Create()
492 cmd.SetArgs([]string{"list"})
493 err := cmd.Execute()
494 if err != nil {
495 t.Errorf("tv list command failed: %v", err)
496 }
497 })
498
499 t.Run("add command with empty args", func(t *testing.T) {
500 cmd := NewTVCommand(handler).Create()
501 cmd.SetArgs([]string{"add"})
502 err := cmd.Execute()
503 if err == nil {
504 t.Error("expected tv add command to fail with empty args")
505 }
506 })
507
508 t.Run("add command with valid args - successful search", func(t *testing.T) {
509 cleanup := services.SetupSuccessfulTVMocks(t)
510 defer cleanup()
511
512 cmd := NewTVCommand(handler).Create()
513 cmd.SetArgs([]string{"add", "Peacemaker"})
514 err := cmd.Execute()
515
516 // NOTE: The command will find results but fail due to no user input in test environment
517 if err == nil {
518 t.Error("expected tv add command to fail due to no user input in test environment")
519 }
520 if !strings.Contains(err.Error(), "invalid input") {
521 t.Errorf("expected 'invalid input' error, got: %v", err)
522 }
523 })
524
525 t.Run("add command with valid args - search failure", func(t *testing.T) {
526 cleanup := services.SetupFailureMocks(t, "tv search failed")
527 defer cleanup()
528
529 cmd := NewTVCommand(handler).Create()
530 cmd.SetArgs([]string{"add", "some show"})
531 err := cmd.Execute()
532 if err == nil {
533 t.Error("expected tv add command to fail when search fails")
534 }
535 services.AssertErrorContains(t, err, "tv search failed")
536 })
537
538 t.Run("remove command with non-existent TV show ID", func(t *testing.T) {
539 cmd := NewTVCommand(handler).Create()
540 cmd.SetArgs([]string{"remove", "999"})
541 err := cmd.Execute()
542 if err == nil {
543 t.Error("expected tv remove command to fail with non-existent ID")
544 }
545 })
546
547 t.Run("remove command with non-numeric ID", func(t *testing.T) {
548 cmd := NewTVCommand(handler).Create()
549 cmd.SetArgs([]string{"remove", "invalid"})
550 err := cmd.Execute()
551 if err == nil {
552 t.Error("expected tv remove command to fail with non-numeric ID")
553 }
554 })
555 })
556
557 t.Run("Book Commands", func(t *testing.T) {
558 handler, cleanup := createTestBookHandler(t)
559 defer cleanup()
560
561 t.Run("list command - default", func(t *testing.T) {
562 cmd := NewBookCommand(handler).Create()
563 cmd.SetArgs([]string{"list"})
564 err := cmd.Execute()
565 if err != nil {
566 t.Errorf("book list command failed: %v", err)
567 }
568 })
569
570 t.Run("remove command with non-existent book ID", func(t *testing.T) {
571 cmd := NewBookCommand(handler).Create()
572 cmd.SetArgs([]string{"remove", "999"})
573 err := cmd.Execute()
574 if err == nil {
575 t.Error("expected book remove command to fail with non-existent ID")
576 }
577 })
578
579 t.Run("remove command with non-numeric ID", func(t *testing.T) {
580 cmd := NewBookCommand(handler).Create()
581 cmd.SetArgs([]string{"remove", "invalid"})
582 err := cmd.Execute()
583 if err == nil {
584 t.Error("expected book remove command to fail with non-numeric ID")
585 }
586 })
587
588 t.Run("update command with removed status", func(t *testing.T) {
589 cmd := NewBookCommand(handler).Create()
590 cmd.SetArgs([]string{"update", "999", "removed"})
591 err := cmd.Execute()
592 if err == nil {
593 t.Error("expected book update command to fail with non-existent ID")
594 }
595 })
596
597 t.Run("update command with invalid status", func(t *testing.T) {
598 cmd := NewBookCommand(handler).Create()
599 cmd.SetArgs([]string{"update", "1", "invalid_status"})
600 err := cmd.Execute()
601 if err == nil {
602 t.Error("expected book update command to fail with invalid status")
603 }
604 })
605 })
606
607 t.Run("Article Commands", func(t *testing.T) {
608 handler, cleanup := createTestArticleHandler(t)
609 defer cleanup()
610
611 t.Run("list command - default", func(t *testing.T) {
612 cmd := NewArticleCommand(handler).Create()
613 cmd.SetArgs([]string{"list"})
614 err := cmd.Execute()
615 if err != nil {
616 t.Errorf("article list command failed: %v", err)
617 }
618 })
619
620 t.Run("help command", func(t *testing.T) {
621 cmd := NewArticleCommand(handler).Create()
622 cmd.SetArgs([]string{"help"})
623 err := cmd.Execute()
624 if err != nil {
625 t.Errorf("article help command failed: %v", err)
626 }
627 })
628
629 t.Run("add command with empty args", func(t *testing.T) {
630 cmd := NewArticleCommand(handler).Create()
631 cmd.SetArgs([]string{"add"})
632 err := cmd.Execute()
633 if err == nil {
634 t.Error("expected article add command to fail with empty args")
635 }
636 })
637
638 t.Run("add command with invalid URL", func(t *testing.T) {
639 cmd := NewArticleCommand(handler).Create()
640 cmd.SetArgs([]string{"add", "not-a-url"})
641 err := cmd.Execute()
642 if err == nil {
643 t.Error("expected article add command to fail with invalid URL")
644 }
645 })
646
647 t.Run("view command with non-existent article ID", func(t *testing.T) {
648 cmd := NewArticleCommand(handler).Create()
649 cmd.SetArgs([]string{"view", "999"})
650 err := cmd.Execute()
651 if err == nil {
652 t.Error("expected article view command to fail with non-existent ID")
653 }
654 })
655
656 t.Run("view command with non-numeric ID", func(t *testing.T) {
657 cmd := NewArticleCommand(handler).Create()
658 cmd.SetArgs([]string{"view", "invalid"})
659 err := cmd.Execute()
660 if err == nil {
661 t.Error("expected article view command to fail with non-numeric ID")
662 }
663 })
664
665 t.Run("remove command with non-existent article ID", func(t *testing.T) {
666 cmd := NewArticleCommand(handler).Create()
667 cmd.SetArgs([]string{"remove", "999"})
668 err := cmd.Execute()
669 if err == nil {
670 t.Error("expected article remove command to fail with non-existent ID")
671 }
672 })
673
674 t.Run("remove command with non-numeric ID", func(t *testing.T) {
675 cmd := NewArticleCommand(handler).Create()
676 cmd.SetArgs([]string{"remove", "invalid"})
677 err := cmd.Execute()
678 if err == nil {
679 t.Error("expected article remove command to fail with non-numeric ID")
680 }
681 })
682 })
683
684 t.Run("Note Commands", func(t *testing.T) {
685 t.Run("create command - non-interactive", func(t *testing.T) {
686 handler, cleanup := createTestNoteHandler(t)
687 defer cleanup()
688
689 cmd := NewNoteCommand(handler).Create()
690 cmd.SetArgs([]string{"create", "test title", "test content"})
691 err := cmd.Execute()
692 if err != nil {
693 t.Errorf("note create command failed: %v", err)
694 }
695 })
696
697 t.Run("list command - static mode", func(t *testing.T) {
698 handler, cleanup := createTestNoteHandler(t)
699 defer cleanup()
700
701 cmd := NewNoteCommand(handler).Create()
702 cmd.SetArgs([]string{"list", "--static"})
703 err := cmd.Execute()
704 if err != nil {
705 t.Errorf("note list command failed: %v", err)
706 }
707 })
708
709 t.Run("read command with valid note ID", func(t *testing.T) {
710 handler, cleanup := createTestNoteHandler(t)
711 defer cleanup()
712
713 err := handler.CreateWithOptions(context.Background(), "test note", "test content", "", false, false)
714 if err != nil {
715 t.Fatalf("failed to create test note: %v", err)
716 }
717
718 cmd := NewNoteCommand(handler).Create()
719 cmd.SetArgs([]string{"read", "1"})
720 err = cmd.Execute()
721 if err != nil {
722 t.Errorf("note read command failed: %v", err)
723 }
724 })
725
726 t.Run("edit command with valid note ID", func(t *testing.T) {
727 t.Skip("edit command requires interactive editor")
728 })
729
730 t.Run("remove command with valid note ID", func(t *testing.T) {
731 handler, cleanup := createTestNoteHandler(t)
732 defer cleanup()
733
734 err := handler.CreateWithOptions(context.Background(), "test note", "test content", "", false, false)
735 if err != nil {
736 t.Fatalf("failed to create test note: %v", err)
737 }
738
739 cmd := NewNoteCommand(handler).Create()
740 cmd.SetArgs([]string{"remove", "1"})
741 err = cmd.Execute()
742 if err != nil {
743 t.Errorf("note remove command failed: %v", err)
744 }
745 })
746 })
747
748 t.Run("Task Commands", func(t *testing.T) {
749 t.Run("list command - static", func(t *testing.T) {
750 handler, cleanup := createTestTaskHandler(t)
751 defer cleanup()
752
753 cmd := NewTaskCommand(handler).Create()
754 cmd.SetArgs([]string{"list", "--static"})
755 err := cmd.Execute()
756 if err != nil {
757 t.Errorf("task list command failed: %v", err)
758 }
759 })
760
761 t.Run("add command with valid args", func(t *testing.T) {
762 handler, cleanup := createTestTaskHandler(t)
763 defer cleanup()
764
765 cmd := NewTaskCommand(handler).Create()
766 cmd.SetArgs([]string{"add", "test task"})
767 err := cmd.Execute()
768 if err != nil {
769 t.Errorf("task add command failed: %v", err)
770 }
771 })
772
773 t.Run("projects command - static", func(t *testing.T) {
774 handler, cleanup := createTestTaskHandler(t)
775 defer cleanup()
776
777 cmd := NewTaskCommand(handler).Create()
778 cmd.SetArgs([]string{"projects", "--static"})
779 err := cmd.Execute()
780 if err != nil {
781 t.Errorf("task projects command failed: %v", err)
782 }
783 })
784
785 t.Run("tags command - static", func(t *testing.T) {
786 handler, cleanup := createTestTaskHandler(t)
787 defer cleanup()
788
789 cmd := NewTaskCommand(handler).Create()
790 cmd.SetArgs([]string{"tags", "--static"})
791 err := cmd.Execute()
792 if err != nil {
793 t.Errorf("task tags command failed: %v", err)
794 }
795 })
796
797 t.Run("contexts command - static", func(t *testing.T) {
798 handler, cleanup := createTestTaskHandler(t)
799 defer cleanup()
800
801 cmd := NewTaskCommand(handler).Create()
802 cmd.SetArgs([]string{"contexts", "--static"})
803 err := cmd.Execute()
804 if err != nil {
805 t.Errorf("task contexts command failed: %v", err)
806 }
807 })
808
809 t.Run("timesheet command", func(t *testing.T) {
810 handler, cleanup := createTestTaskHandler(t)
811 defer cleanup()
812
813 cmd := NewTaskCommand(handler).Create()
814 cmd.SetArgs([]string{"timesheet"})
815 err := cmd.Execute()
816 if err != nil {
817 t.Errorf("task timesheet command failed: %v", err)
818 }
819 })
820 })
821}