cli + tui to publish to leaflet (wip) & manage tasks, notes & watch/read lists 馃崈
charm leaflet readability golang
at main 204 lines 5.4 kB view raw
1package main 2 3import ( 4 "bytes" 5 "context" 6 "errors" 7 "strings" 8 "testing" 9 10 "github.com/charmbracelet/fang" 11 "github.com/spf13/cobra" 12 "github.com/stormlightlabs/noteleaf/internal/handlers" 13 "github.com/stormlightlabs/noteleaf/internal/store" 14) 15 16func executeCommand(t *testing.T, cmd *cobra.Command, args ...string) string { 17 buf := &bytes.Buffer{} 18 cmd.SetOut(buf) 19 cmd.SetArgs(args) 20 if err := cmd.Execute(); err != nil { 21 t.Fatalf("command %q failed: %v", args, err) 22 } 23 return buf.String() 24} 25 26func TestNewApp(t *testing.T) { 27 t.Run("Success", func(t *testing.T) { 28 origDB := store.NewDatabase 29 origConfig := store.LoadConfig 30 defer func() { 31 store.NewDatabase = origDB 32 store.LoadConfig = origConfig 33 }() 34 35 store.NewDatabase = func() (*store.Database, error) { return &store.Database{}, nil } 36 store.LoadConfig = func() (*store.Config, error) { return &store.Config{}, nil } 37 38 app, err := NewApp() 39 if err != nil { 40 t.Fatalf("expected no error, got %v", err) 41 } 42 if app.db == nil || app.config == nil { 43 t.Fatalf("expected db and config to be initialized") 44 } 45 }) 46 47 t.Run("DBError", func(t *testing.T) { 48 origDB := store.NewDatabase 49 defer func() { store.NewDatabase = origDB }() 50 store.NewDatabase = func() (*store.Database, error) { return nil, errors.New("db boom") } 51 52 _, err := NewApp() 53 if err == nil || !strings.Contains(err.Error(), "failed to initialize database") { 54 t.Errorf("expected db init error, got %v", err) 55 } 56 }) 57 58 t.Run("ConfigError", func(t *testing.T) { 59 origDB := store.NewDatabase 60 origConfig := store.LoadConfig 61 defer func() { 62 store.NewDatabase = origDB 63 store.LoadConfig = origConfig 64 }() 65 store.NewDatabase = func() (*store.Database, error) { return &store.Database{}, nil } 66 store.LoadConfig = func() (*store.Config, error) { return nil, errors.New("config boom") } 67 68 _, err := NewApp() 69 if err == nil || !strings.Contains(err.Error(), "failed to load configuration") { 70 t.Errorf("expected config load error, got %v", err) 71 } 72 }) 73} 74 75func TestRootCmd(t *testing.T) { 76 t.Run("Help", func(t *testing.T) { 77 root := rootCmd() 78 root.SetArgs([]string{}) 79 if err := root.Execute(); err != nil { 80 t.Fatalf("expected no error, got %v", err) 81 } 82 }) 83 84 t.Run("PrintArgs", func(t *testing.T) { 85 root := rootCmd() 86 root.SetArgs([]string{"hello", "world"}) 87 buf := &bytes.Buffer{} 88 root.SetOut(buf) 89 90 if err := root.Execute(); err != nil { 91 t.Fatalf("unexpected error: %v", err) 92 } 93 if got := buf.String(); !strings.Contains(got, "hello world") { 94 t.Errorf("expected output to contain 'hello world', got %q", got) 95 } 96 }) 97} 98 99func TestStatusCmd(t *testing.T) { 100 output := executeCommand(t, statusCmd(), nil...) 101 if output == "" { 102 t.Errorf("expected some status output, got empty string") 103 } 104} 105 106func TestResetCmd(t *testing.T) { 107 _ = executeCommand(t, resetCmd(), nil...) 108} 109 110func TestSetupCmd(t *testing.T) { 111 _ = executeCommand(t, setupCmd(), nil...) 112} 113 114func TestConfCmd(t *testing.T) { 115 cmd := confCmd() 116 buf := &bytes.Buffer{} 117 cmd.SetOut(buf) 118 cmd.SetArgs([]string{"path"}) 119 120 if err := cmd.Execute(); err != nil { 121 t.Errorf("config path command failed: %v", err) 122 } 123} 124 125func TestRun(t *testing.T) { 126 t.Run("Success", func(t *testing.T) { 127 code := run() 128 if code != 0 { 129 t.Errorf("expected exit code 0, got %d", code) 130 } 131 }) 132 133 t.Run("TaskHandlerError", func(t *testing.T) { 134 orig := newTaskHandler 135 defer func() { newTaskHandler = orig }() 136 newTaskHandler = func() (*handlers.TaskHandler, error) { return nil, errors.New("boom") } 137 138 if code := run(); code != 1 { 139 t.Errorf("expected exit code 1, got %d", code) 140 } 141 }) 142 143 t.Run("MovieHandlerError", func(t *testing.T) { 144 orig := newMovieHandler 145 defer func() { newMovieHandler = orig }() 146 newMovieHandler = func() (*handlers.MovieHandler, error) { return nil, errors.New("boom") } 147 148 if code := run(); code != 1 { 149 t.Errorf("expected exit code 1, got %d", code) 150 } 151 }) 152 153 t.Run("TVHandlerError", func(t *testing.T) { 154 orig := newTVHandler 155 defer func() { newTVHandler = orig }() 156 newTVHandler = func() (*handlers.TVHandler, error) { return nil, errors.New("boom") } 157 158 if code := run(); code != 1 { 159 t.Errorf("expected exit code 1, got %d", code) 160 } 161 }) 162 163 t.Run("NoteHandlerError", func(t *testing.T) { 164 orig := newNoteHandler 165 defer func() { newNoteHandler = orig }() 166 newNoteHandler = func() (*handlers.NoteHandler, error) { return nil, errors.New("boom") } 167 168 if code := run(); code != 1 { 169 t.Errorf("expected exit code 1, got %d", code) 170 } 171 }) 172 173 t.Run("BookHandlerError", func(t *testing.T) { 174 orig := newBookHandler 175 defer func() { newBookHandler = orig }() 176 newBookHandler = func() (*handlers.BookHandler, error) { return nil, errors.New("boom") } 177 178 if code := run(); code != 1 { 179 t.Errorf("expected exit code 1, got %d", code) 180 } 181 }) 182 183 t.Run("ArticleHandlerError", func(t *testing.T) { 184 orig := newArticleHandler 185 defer func() { newArticleHandler = orig }() 186 newArticleHandler = func() (*handlers.ArticleHandler, error) { return nil, errors.New("boom") } 187 188 if code := run(); code != 1 { 189 t.Errorf("expected exit code 1, got %d", code) 190 } 191 }) 192 193 t.Run("FangExecuteError", func(t *testing.T) { 194 orig := exc 195 defer func() { exc = orig }() 196 exc = func(ctx context.Context, cmd *cobra.Command, opts ...fang.Option) error { 197 return errors.New("fang failed") 198 } 199 200 if code := run(); code != 1 { 201 t.Errorf("expected exit code 1, got %d", code) 202 } 203 }) 204}