fizzy-cli 0.8.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/.golangci.yml +56 -0
  2. package/IMPLEMENTATION_PLAN.md +58 -0
  3. package/docs/API.md +89 -0
  4. package/package.json +2 -1
  5. package/.env +0 -1
  6. package/.github/workflows/release.yml +0 -29
  7. package/.github/workflows/tests.yml +0 -24
  8. package/AGENTS.md +0 -33
  9. package/CHANGELOG.md +0 -194
  10. package/Makefile +0 -43
  11. package/bin/fizzy +0 -0
  12. package/cmd/account.go +0 -14
  13. package/cmd/account_list.go +0 -44
  14. package/cmd/account_list_test.go +0 -118
  15. package/cmd/board.go +0 -49
  16. package/cmd/board_create.go +0 -59
  17. package/cmd/board_create_test.go +0 -141
  18. package/cmd/board_delete.go +0 -40
  19. package/cmd/board_delete_test.go +0 -121
  20. package/cmd/board_list.go +0 -44
  21. package/cmd/board_list_test.go +0 -115
  22. package/cmd/board_show.go +0 -40
  23. package/cmd/board_show_test.go +0 -113
  24. package/cmd/board_test.go +0 -92
  25. package/cmd/board_update.go +0 -72
  26. package/cmd/board_update_test.go +0 -233
  27. package/cmd/card.go +0 -24
  28. package/cmd/card_assign.go +0 -55
  29. package/cmd/card_assign_test.go +0 -130
  30. package/cmd/card_close.go +0 -46
  31. package/cmd/card_close_test.go +0 -92
  32. package/cmd/card_create.go +0 -72
  33. package/cmd/card_create_test.go +0 -186
  34. package/cmd/card_delete.go +0 -46
  35. package/cmd/card_delete_test.go +0 -92
  36. package/cmd/card_golden.go +0 -46
  37. package/cmd/card_golden_test.go +0 -92
  38. package/cmd/card_list.go +0 -114
  39. package/cmd/card_list_test.go +0 -373
  40. package/cmd/card_not_now.go +0 -46
  41. package/cmd/card_not_now_test.go +0 -92
  42. package/cmd/card_reaction.go +0 -13
  43. package/cmd/card_reaction_create.go +0 -46
  44. package/cmd/card_reaction_create_test.go +0 -148
  45. package/cmd/card_reaction_delete.go +0 -46
  46. package/cmd/card_reaction_delete_test.go +0 -112
  47. package/cmd/card_reaction_list.go +0 -51
  48. package/cmd/card_reaction_list_test.go +0 -127
  49. package/cmd/card_reopen.go +0 -46
  50. package/cmd/card_reopen_test.go +0 -92
  51. package/cmd/card_show.go +0 -46
  52. package/cmd/card_show_test.go +0 -92
  53. package/cmd/card_tag.go +0 -51
  54. package/cmd/card_tag_test.go +0 -112
  55. package/cmd/card_triage.go +0 -46
  56. package/cmd/card_ungolden.go +0 -46
  57. package/cmd/card_ungolden_test.go +0 -92
  58. package/cmd/card_untriage.go +0 -46
  59. package/cmd/card_untriage_test.go +0 -92
  60. package/cmd/card_unwatch.go +0 -46
  61. package/cmd/card_unwatch_test.go +0 -92
  62. package/cmd/card_update.go +0 -82
  63. package/cmd/card_update_test.go +0 -149
  64. package/cmd/card_watch.go +0 -46
  65. package/cmd/card_watch_test.go +0 -92
  66. package/cmd/column.go +0 -14
  67. package/cmd/column_create.go +0 -79
  68. package/cmd/column_create_test.go +0 -178
  69. package/cmd/column_delete.go +0 -40
  70. package/cmd/column_delete_test.go +0 -121
  71. package/cmd/column_list.go +0 -44
  72. package/cmd/column_list_test.go +0 -138
  73. package/cmd/column_show.go +0 -40
  74. package/cmd/column_show_test.go +0 -111
  75. package/cmd/column_update.go +0 -67
  76. package/cmd/column_update_test.go +0 -198
  77. package/cmd/comment.go +0 -14
  78. package/cmd/comment_create.go +0 -51
  79. package/cmd/comment_create_test.go +0 -129
  80. package/cmd/comment_delete.go +0 -46
  81. package/cmd/comment_delete_test.go +0 -92
  82. package/cmd/comment_list.go +0 -51
  83. package/cmd/comment_list_test.go +0 -132
  84. package/cmd/comment_show.go +0 -46
  85. package/cmd/comment_show_test.go +0 -104
  86. package/cmd/comment_update.go +0 -51
  87. package/cmd/comment_update_test.go +0 -130
  88. package/cmd/login.go +0 -81
  89. package/cmd/login_test.go +0 -98
  90. package/cmd/notification.go +0 -14
  91. package/cmd/notification_list.go +0 -69
  92. package/cmd/notification_list_test.go +0 -288
  93. package/cmd/notification_read.go +0 -51
  94. package/cmd/notification_read_all.go +0 -38
  95. package/cmd/notification_read_all_test.go +0 -75
  96. package/cmd/notification_read_test.go +0 -138
  97. package/cmd/notification_unread.go +0 -44
  98. package/cmd/notification_unread_test.go +0 -99
  99. package/cmd/reaction.go +0 -13
  100. package/cmd/reaction_create.go +0 -46
  101. package/cmd/reaction_create_test.go +0 -113
  102. package/cmd/reaction_delete.go +0 -46
  103. package/cmd/reaction_delete_test.go +0 -92
  104. package/cmd/reaction_list.go +0 -51
  105. package/cmd/reaction_list_test.go +0 -125
  106. package/cmd/root.go +0 -38
  107. package/cmd/step.go +0 -14
  108. package/cmd/step_create.go +0 -53
  109. package/cmd/step_create_test.go +0 -171
  110. package/cmd/step_delete.go +0 -46
  111. package/cmd/step_delete_test.go +0 -92
  112. package/cmd/step_update.go +0 -66
  113. package/cmd/step_update_test.go +0 -190
  114. package/cmd/tag.go +0 -15
  115. package/cmd/tag_list.go +0 -47
  116. package/cmd/tag_list_test.go +0 -109
  117. package/cmd/use.go +0 -85
  118. package/cmd/use_test.go +0 -186
  119. package/cmd/user.go +0 -22
  120. package/cmd/user_deactivate.go +0 -40
  121. package/cmd/user_deactivate_test.go +0 -121
  122. package/cmd/user_list.go +0 -44
  123. package/cmd/user_list_test.go +0 -126
  124. package/cmd/user_show.go +0 -40
  125. package/cmd/user_show_test.go +0 -110
  126. package/cmd/user_update.go +0 -71
  127. package/cmd/user_update_test.go +0 -177
  128. package/go.mod +0 -31
  129. package/go.sum +0 -53
  130. package/internal/api/boards.go +0 -93
  131. package/internal/api/cards.go +0 -322
  132. package/internal/api/client.go +0 -99
  133. package/internal/api/columns.go +0 -113
  134. package/internal/api/comments.go +0 -108
  135. package/internal/api/identity.go +0 -24
  136. package/internal/api/notifications.go +0 -89
  137. package/internal/api/reactions.go +0 -130
  138. package/internal/api/steps.go +0 -101
  139. package/internal/api/tags.go +0 -24
  140. package/internal/api/types.go +0 -195
  141. package/internal/api/users.go +0 -75
  142. package/internal/app/app.go +0 -49
  143. package/internal/colors/colors.go +0 -32
  144. package/internal/config/config.go +0 -70
  145. package/internal/testutil/client.go +0 -26
  146. package/internal/ui/account_list.go +0 -14
  147. package/internal/ui/account_selector.go +0 -63
  148. package/internal/ui/board_list.go +0 -14
  149. package/internal/ui/board_show.go +0 -17
  150. package/internal/ui/card_list.go +0 -14
  151. package/internal/ui/card_show.go +0 -23
  152. package/internal/ui/column_list.go +0 -28
  153. package/internal/ui/column_show.go +0 -16
  154. package/internal/ui/comment_list.go +0 -25
  155. package/internal/ui/format.go +0 -27
  156. package/internal/ui/notification_list.go +0 -27
  157. package/internal/ui/reaction_list.go +0 -14
  158. package/internal/ui/user_list.go +0 -19
  159. package/internal/ui/user_show.go +0 -23
@@ -1,178 +0,0 @@
1
- package cmd
2
-
3
- import (
4
- "context"
5
- "encoding/json"
6
- "io"
7
- "net/http"
8
- "net/http/httptest"
9
- "testing"
10
-
11
- "github.com/rogeriopvl/fizzy/internal/api"
12
- "github.com/rogeriopvl/fizzy/internal/app"
13
- "github.com/rogeriopvl/fizzy/internal/testutil"
14
- )
15
-
16
- func TestColumnCreateCommandSuccess(t *testing.T) {
17
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
18
- if r.URL.Path != "/boards/board-123/columns" {
19
- t.Errorf("expected /boards/board-123/columns, got %s", r.URL.Path)
20
- }
21
- if r.Method != http.MethodPost {
22
- t.Errorf("expected POST, got %s", r.Method)
23
- }
24
-
25
- auth := r.Header.Get("Authorization")
26
- if auth != "Bearer test-token" {
27
- t.Errorf("expected Bearer test-token, got %s", auth)
28
- }
29
-
30
- if r.Header.Get("Content-Type") != "application/json" {
31
- t.Errorf("expected Content-Type: application/json, got %s", r.Header.Get("Content-Type"))
32
- }
33
-
34
- body, _ := io.ReadAll(r.Body)
35
- var payload map[string]api.CreateColumnPayload
36
- if err := json.Unmarshal(body, &payload); err != nil {
37
- t.Fatalf("failed to unmarshal request body: %v", err)
38
- }
39
-
40
- columnPayload := payload["column"]
41
- if columnPayload.Name != "Todo" {
42
- t.Errorf("expected name 'Todo', got %s", columnPayload.Name)
43
- }
44
- if columnPayload.Color != nil {
45
- t.Errorf("expected no color, got %v", columnPayload.Color)
46
- }
47
-
48
- w.WriteHeader(http.StatusCreated)
49
- w.Header().Set("Location", "/columns/col-123")
50
- }))
51
- defer server.Close()
52
-
53
- client := testutil.NewTestClient(server.URL, "", "board-123", "test-token")
54
- testApp := &app.App{Client: client}
55
-
56
- cmd := columnCreateCmd
57
- cmd.SetContext(testApp.ToContext(context.Background()))
58
- cmd.ParseFlags([]string{"--name", "Todo"})
59
-
60
- if err := handleCreateColumn(cmd); err != nil {
61
- t.Fatalf("handleCreateColumn failed: %v", err)
62
- }
63
- }
64
-
65
- func TestColumnCreateCommandWithColor(t *testing.T) {
66
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
67
- if r.Method != http.MethodPost {
68
- t.Errorf("expected POST, got %s", r.Method)
69
- }
70
-
71
- body, _ := io.ReadAll(r.Body)
72
- var payload map[string]api.CreateColumnPayload
73
- json.Unmarshal(body, &payload)
74
-
75
- columnPayload := payload["column"]
76
- if columnPayload.Name != "In Progress" {
77
- t.Errorf("expected name 'In Progress', got %s", columnPayload.Name)
78
- }
79
- if columnPayload.Color == nil {
80
- t.Error("expected color to be set")
81
- }
82
- if *columnPayload.Color != "var(--color-card-4)" {
83
- t.Errorf("expected color 'var(--color-card-4)', got %s", *columnPayload.Color)
84
- }
85
-
86
- w.WriteHeader(http.StatusCreated)
87
- }))
88
- defer server.Close()
89
-
90
- client := testutil.NewTestClient(server.URL, "", "board-123", "test-token")
91
- testApp := &app.App{Client: client}
92
-
93
- cmd := columnCreateCmd
94
- cmd.SetContext(testApp.ToContext(context.Background()))
95
- cmd.ParseFlags([]string{"--name", "In Progress", "--color", "lime"})
96
-
97
- if err := handleCreateColumn(cmd); err != nil {
98
- t.Fatalf("handleCreateColumn failed: %v", err)
99
- }
100
- }
101
-
102
- func TestColumnCreateCommandInvalidColor(t *testing.T) {
103
- client := testutil.NewTestClient("http://localhost", "", "board-123", "test-token")
104
- testApp := &app.App{Client: client}
105
-
106
- cmd := columnCreateCmd
107
- cmd.SetContext(testApp.ToContext(context.Background()))
108
- cmd.ParseFlags([]string{"--name", "Todo", "--color", "invalid"})
109
-
110
- err := handleCreateColumn(cmd)
111
- if err == nil {
112
- t.Errorf("expected error for invalid color")
113
- }
114
- if err.Error() != "invalid color 'invalid'. Available colors: blue, gray, tan, yellow, lime, aqua, violet, purple, pink" {
115
- t.Errorf("expected invalid color error, got %v", err)
116
- }
117
- }
118
-
119
- func TestColumnCreateCommandNoBoard(t *testing.T) {
120
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
121
- w.WriteHeader(http.StatusInternalServerError)
122
- }))
123
- defer server.Close()
124
-
125
- client := testutil.NewTestClient(server.URL, "", "", "test-token")
126
- testApp := &app.App{Client: client}
127
-
128
- cmd := columnCreateCmd
129
- cmd.SetContext(testApp.ToContext(context.Background()))
130
- cmd.ParseFlags([]string{"--name", "Todo", "--color", ""})
131
-
132
- err := handleCreateColumn(cmd)
133
- if err == nil {
134
- t.Errorf("expected error when board not selected")
135
- }
136
- if err.Error() != "creating column: please select a board first with 'fizzy use --board <board_name>'" {
137
- t.Errorf("expected 'board not selected' error, got %v", err)
138
- }
139
- }
140
-
141
- func TestColumnCreateCommandNoClient(t *testing.T) {
142
- testApp := &app.App{}
143
-
144
- cmd := columnCreateCmd
145
- cmd.SetContext(testApp.ToContext(context.Background()))
146
- cmd.ParseFlags([]string{"--name", "Todo", "--color", ""})
147
-
148
- err := handleCreateColumn(cmd)
149
- if err == nil {
150
- t.Errorf("expected error when client not available")
151
- }
152
- if err.Error() != "API client not available" {
153
- t.Errorf("expected 'client not available' error, got %v", err)
154
- }
155
- }
156
-
157
- func TestColumnCreateCommandAPIError(t *testing.T) {
158
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
159
- w.WriteHeader(http.StatusInternalServerError)
160
- w.Write([]byte("Internal Server Error"))
161
- }))
162
- defer server.Close()
163
-
164
- client := testutil.NewTestClient(server.URL, "", "board-123", "test-token")
165
- testApp := &app.App{Client: client}
166
-
167
- cmd := columnCreateCmd
168
- cmd.SetContext(testApp.ToContext(context.Background()))
169
- cmd.ParseFlags([]string{"--name", "Todo", "--color", ""})
170
-
171
- err := handleCreateColumn(cmd)
172
- if err == nil {
173
- t.Errorf("expected error for API failure")
174
- }
175
- if err.Error() != "creating column: unexpected status code 500: Internal Server Error" {
176
- t.Errorf("expected API error, got %v", err)
177
- }
178
- }
@@ -1,40 +0,0 @@
1
- package cmd
2
-
3
- import (
4
- "context"
5
- "fmt"
6
-
7
- "github.com/rogeriopvl/fizzy/internal/app"
8
- "github.com/spf13/cobra"
9
- )
10
-
11
- var columnDeleteCmd = &cobra.Command{
12
- Use: "delete <column_id>",
13
- Short: "Delete a column",
14
- Long: `Delete a column. Only board administrators can delete columns.`,
15
- Args: cobra.ExactArgs(1),
16
- Run: func(cmd *cobra.Command, args []string) {
17
- if err := handleDeleteColumn(cmd, args[0]); err != nil {
18
- fmt.Fprintf(cmd.OutOrStderr(), "Error: %v\n", err)
19
- }
20
- },
21
- }
22
-
23
- func handleDeleteColumn(cmd *cobra.Command, columnID string) error {
24
- a := app.FromContext(cmd.Context())
25
- if a == nil || a.Client == nil {
26
- return fmt.Errorf("API client not available")
27
- }
28
-
29
- err := a.Client.DeleteColumn(context.Background(), columnID)
30
- if err != nil {
31
- return fmt.Errorf("deleting column: %w", err)
32
- }
33
-
34
- fmt.Fprintf(cmd.OutOrStdout(), "✓ Column '%s' deleted successfully\n", columnID)
35
- return nil
36
- }
37
-
38
- func init() {
39
- columnCmd.AddCommand(columnDeleteCmd)
40
- }
@@ -1,121 +0,0 @@
1
- package cmd
2
-
3
- import (
4
- "context"
5
- "net/http"
6
- "net/http/httptest"
7
- "testing"
8
-
9
- "github.com/rogeriopvl/fizzy/internal/app"
10
- "github.com/rogeriopvl/fizzy/internal/testutil"
11
- )
12
-
13
- func TestColumnDeleteCommandSuccess(t *testing.T) {
14
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
15
- if r.URL.Path != "/boards/board-123/columns/col-456" {
16
- t.Errorf("expected /boards/board-123/columns/col-456, got %s", r.URL.Path)
17
- }
18
- if r.Method != http.MethodDelete {
19
- t.Errorf("expected DELETE, got %s", r.Method)
20
- }
21
-
22
- auth := r.Header.Get("Authorization")
23
- if auth != "Bearer test-token" {
24
- t.Errorf("expected Bearer test-token, got %s", auth)
25
- }
26
-
27
- w.WriteHeader(http.StatusNoContent)
28
- }))
29
- defer server.Close()
30
-
31
- client := testutil.NewTestClient(server.URL, "", "board-123", "test-token")
32
- testApp := &app.App{Client: client}
33
-
34
- cmd := columnDeleteCmd
35
- cmd.SetContext(testApp.ToContext(context.Background()))
36
-
37
- if err := handleDeleteColumn(cmd, "col-456"); err != nil {
38
- t.Fatalf("handleDeleteColumn failed: %v", err)
39
- }
40
- }
41
-
42
- func TestColumnDeleteCommandNotFound(t *testing.T) {
43
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
44
- w.WriteHeader(http.StatusNotFound)
45
- w.Write([]byte("Column not found"))
46
- }))
47
- defer server.Close()
48
-
49
- client := testutil.NewTestClient(server.URL, "", "board-123", "test-token")
50
- testApp := &app.App{Client: client}
51
-
52
- cmd := columnDeleteCmd
53
- cmd.SetContext(testApp.ToContext(context.Background()))
54
-
55
- err := handleDeleteColumn(cmd, "nonexistent-col")
56
- if err == nil {
57
- t.Errorf("expected error for column not found")
58
- }
59
- if err.Error() != "deleting column: unexpected status code 404: Column not found" {
60
- t.Errorf("expected column not found error, got %v", err)
61
- }
62
- }
63
-
64
- func TestColumnDeleteCommandForbidden(t *testing.T) {
65
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
66
- w.WriteHeader(http.StatusForbidden)
67
- w.Write([]byte("You don't have permission to delete this column"))
68
- }))
69
- defer server.Close()
70
-
71
- client := testutil.NewTestClient(server.URL, "", "board-123", "test-token")
72
- testApp := &app.App{Client: client}
73
-
74
- cmd := columnDeleteCmd
75
- cmd.SetContext(testApp.ToContext(context.Background()))
76
-
77
- err := handleDeleteColumn(cmd, "col-456")
78
- if err == nil {
79
- t.Errorf("expected error for forbidden access")
80
- }
81
- if err.Error() != "deleting column: unexpected status code 403: You don't have permission to delete this column" {
82
- t.Errorf("expected permission error, got %v", err)
83
- }
84
- }
85
-
86
- func TestColumnDeleteCommandAPIError(t *testing.T) {
87
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
88
- w.WriteHeader(http.StatusInternalServerError)
89
- w.Write([]byte("Internal Server Error"))
90
- }))
91
- defer server.Close()
92
-
93
- client := testutil.NewTestClient(server.URL, "", "board-123", "test-token")
94
- testApp := &app.App{Client: client}
95
-
96
- cmd := columnDeleteCmd
97
- cmd.SetContext(testApp.ToContext(context.Background()))
98
-
99
- err := handleDeleteColumn(cmd, "col-456")
100
- if err == nil {
101
- t.Errorf("expected error for API failure")
102
- }
103
- if err.Error() != "deleting column: unexpected status code 500: Internal Server Error" {
104
- t.Errorf("expected API error, got %v", err)
105
- }
106
- }
107
-
108
- func TestColumnDeleteCommandNoClient(t *testing.T) {
109
- testApp := &app.App{}
110
-
111
- cmd := columnDeleteCmd
112
- cmd.SetContext(testApp.ToContext(context.Background()))
113
-
114
- err := handleDeleteColumn(cmd, "col-456")
115
- if err == nil {
116
- t.Errorf("expected error when client not available")
117
- }
118
- if err.Error() != "API client not available" {
119
- t.Errorf("expected 'client not available' error, got %v", err)
120
- }
121
- }
@@ -1,44 +0,0 @@
1
- package cmd
2
-
3
- import (
4
- "context"
5
- "fmt"
6
-
7
- "github.com/rogeriopvl/fizzy/internal/app"
8
- "github.com/rogeriopvl/fizzy/internal/ui"
9
- "github.com/spf13/cobra"
10
- )
11
-
12
- var columnListCmd = &cobra.Command{
13
- Use: "list",
14
- Short: "List all columns",
15
- Long: `Retrieve and display all columns in the selected board`,
16
- Run: func(cmd *cobra.Command, args []string) {
17
- if err := handleListColumns(cmd); err != nil {
18
- fmt.Fprintf(cmd.OutOrStderr(), "Error: %v\n", err)
19
- }
20
- },
21
- }
22
-
23
- func handleListColumns(cmd *cobra.Command) error {
24
- a := app.FromContext(cmd.Context())
25
- if a == nil || a.Client == nil {
26
- return fmt.Errorf("API client not available")
27
- }
28
-
29
- columns, err := a.Client.GetColumns(context.Background())
30
- if err != nil {
31
- return fmt.Errorf("fetching columns: %w", err)
32
- }
33
-
34
- if len(columns) == 0 {
35
- fmt.Println("No columns found")
36
- return nil
37
- }
38
-
39
- return ui.DisplayColumns(columns)
40
- }
41
-
42
- func init() {
43
- columnCmd.AddCommand(columnListCmd)
44
- }
@@ -1,138 +0,0 @@
1
- package cmd
2
-
3
- import (
4
- "context"
5
- "encoding/json"
6
- "net/http"
7
- "net/http/httptest"
8
- "testing"
9
-
10
- "github.com/rogeriopvl/fizzy/internal/api"
11
- "github.com/rogeriopvl/fizzy/internal/app"
12
- "github.com/rogeriopvl/fizzy/internal/testutil"
13
- )
14
-
15
- func TestColumnListCommand(t *testing.T) {
16
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
17
- if r.URL.Path != "/boards/board-123/columns" {
18
- t.Errorf("expected /boards/board-123/columns, got %s", r.URL.Path)
19
- }
20
- if r.Method != http.MethodGet {
21
- t.Errorf("expected GET, got %s", r.Method)
22
- }
23
-
24
- auth := r.Header.Get("Authorization")
25
- if auth != "Bearer test-token" {
26
- t.Errorf("expected Bearer test-token, got %s", auth)
27
- }
28
-
29
- if r.Header.Get("Accept") != "application/json" {
30
- t.Errorf("expected Accept: application/json, got %s", r.Header.Get("Accept"))
31
- }
32
-
33
- w.Header().Set("Content-Type", "application/json")
34
- response := []api.Column{
35
- {
36
- ID: "col-123",
37
- Name: "Todo",
38
- Color: api.ColorObject{
39
- Name: "Blue",
40
- Value: "var(--color-card-default)",
41
- },
42
- CreatedAt: "2025-01-01T00:00:00Z",
43
- },
44
- {
45
- ID: "col-456",
46
- Name: "In Progress",
47
- Color: api.ColorObject{
48
- Name: "Lime",
49
- Value: "var(--color-card-4)",
50
- },
51
- CreatedAt: "2025-01-02T00:00:00Z",
52
- },
53
- }
54
- json.NewEncoder(w).Encode(response)
55
- }))
56
- defer server.Close()
57
-
58
- client := testutil.NewTestClient(server.URL, "", "board-123", "test-token")
59
- testApp := &app.App{Client: client}
60
-
61
- cmd := columnListCmd
62
- cmd.SetContext(testApp.ToContext(context.Background()))
63
-
64
- if err := handleListColumns(cmd); err != nil {
65
- t.Fatalf("handleListColumns failed: %v", err)
66
- }
67
- }
68
-
69
- func TestColumnListCommandNoColumns(t *testing.T) {
70
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
71
- w.Header().Set("Content-Type", "application/json")
72
- json.NewEncoder(w).Encode([]api.Column{})
73
- }))
74
- defer server.Close()
75
-
76
- client := testutil.NewTestClient(server.URL, "", "board-123", "test-token")
77
- testApp := &app.App{Client: client}
78
-
79
- cmd := columnListCmd
80
- cmd.SetContext(testApp.ToContext(context.Background()))
81
-
82
- if err := handleListColumns(cmd); err != nil {
83
- t.Fatalf("handleListColumns failed: %v", err)
84
- }
85
- }
86
-
87
- func TestColumnListCommandAPIError(t *testing.T) {
88
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
89
- w.WriteHeader(http.StatusInternalServerError)
90
- w.Write([]byte("Internal Server Error"))
91
- }))
92
- defer server.Close()
93
-
94
- client := testutil.NewTestClient(server.URL, "", "board-123", "test-token")
95
- testApp := &app.App{Client: client}
96
-
97
- cmd := columnListCmd
98
- cmd.SetContext(testApp.ToContext(context.Background()))
99
-
100
- err := handleListColumns(cmd)
101
- if err == nil {
102
- t.Errorf("expected error for API failure")
103
- }
104
- if err.Error() != "fetching columns: unexpected status code 500: Internal Server Error" {
105
- t.Errorf("expected API error, got %v", err)
106
- }
107
- }
108
-
109
- func TestColumnListCommandNoBoard(t *testing.T) {
110
- client := testutil.NewTestClient("http://localhost", "", "", "test-token")
111
- testApp := &app.App{Client: client}
112
-
113
- cmd := columnListCmd
114
- cmd.SetContext(testApp.ToContext(context.Background()))
115
-
116
- err := handleListColumns(cmd)
117
- if err == nil {
118
- t.Errorf("expected error when board not selected")
119
- }
120
- if err.Error() != "fetching columns: please select a board first with 'fizzy use --board <board_name>'" {
121
- t.Errorf("expected 'board not selected' error, got %v", err)
122
- }
123
- }
124
-
125
- func TestColumnListCommandNoClient(t *testing.T) {
126
- testApp := &app.App{}
127
-
128
- cmd := columnListCmd
129
- cmd.SetContext(testApp.ToContext(context.Background()))
130
-
131
- err := handleListColumns(cmd)
132
- if err == nil {
133
- t.Errorf("expected error when client not available")
134
- }
135
- if err.Error() != "API client not available" {
136
- t.Errorf("expected 'client not available' error, got %v", err)
137
- }
138
- }
@@ -1,40 +0,0 @@
1
- package cmd
2
-
3
- import (
4
- "context"
5
- "fmt"
6
-
7
- "github.com/rogeriopvl/fizzy/internal/app"
8
- "github.com/rogeriopvl/fizzy/internal/ui"
9
- "github.com/spf13/cobra"
10
- )
11
-
12
- var columnShowCmd = &cobra.Command{
13
- Use: "show <column_id>",
14
- Short: "Show column details",
15
- Long: `Retrieve and display detailed information about a specific column`,
16
- Args: cobra.ExactArgs(1),
17
- Run: func(cmd *cobra.Command, args []string) {
18
- if err := handleShowColumnDetails(cmd, args[0]); err != nil {
19
- fmt.Fprintf(cmd.OutOrStderr(), "Error: %v\n", err)
20
- }
21
- },
22
- }
23
-
24
- func handleShowColumnDetails(cmd *cobra.Command, columnID string) error {
25
- a := app.FromContext(cmd.Context())
26
- if a == nil || a.Client == nil {
27
- return fmt.Errorf("API client not available")
28
- }
29
-
30
- column, err := a.Client.GetColumn(context.Background(), columnID)
31
- if err != nil {
32
- return fmt.Errorf("fetching column: %w", err)
33
- }
34
-
35
- return ui.DisplayColumn(cmd.OutOrStdout(), column)
36
- }
37
-
38
- func init() {
39
- columnCmd.AddCommand(columnShowCmd)
40
- }
@@ -1,111 +0,0 @@
1
- package cmd
2
-
3
- import (
4
- "context"
5
- "encoding/json"
6
- "net/http"
7
- "net/http/httptest"
8
- "testing"
9
-
10
- "github.com/rogeriopvl/fizzy/internal/api"
11
- "github.com/rogeriopvl/fizzy/internal/app"
12
- "github.com/rogeriopvl/fizzy/internal/testutil"
13
- )
14
-
15
- func TestColumnShowCommandSuccess(t *testing.T) {
16
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
17
- if r.URL.Path != "/boards/board-123/columns/col-456" {
18
- t.Errorf("expected /boards/board-123/columns/col-456, got %s", r.URL.Path)
19
- }
20
- if r.Method != http.MethodGet {
21
- t.Errorf("expected GET, got %s", r.Method)
22
- }
23
-
24
- auth := r.Header.Get("Authorization")
25
- if auth != "Bearer test-token" {
26
- t.Errorf("expected Bearer test-token, got %s", auth)
27
- }
28
-
29
- w.Header().Set("Content-Type", "application/json")
30
- response := api.Column{
31
- ID: "col-456",
32
- Name: "In Progress",
33
- CreatedAt: "2025-01-01T00:00:00Z",
34
- Color: api.ColorObject{
35
- Name: "Lime",
36
- Value: api.Lime,
37
- },
38
- }
39
- json.NewEncoder(w).Encode(response)
40
- }))
41
- defer server.Close()
42
-
43
- client := testutil.NewTestClient(server.URL, "", "board-123", "test-token")
44
- testApp := &app.App{Client: client}
45
-
46
- cmd := columnShowCmd
47
- cmd.SetContext(testApp.ToContext(context.Background()))
48
-
49
- if err := handleShowColumnDetails(cmd, "col-456"); err != nil {
50
- t.Fatalf("handleShowColumnDetails failed: %v", err)
51
- }
52
- }
53
-
54
- func TestColumnShowCommandNotFound(t *testing.T) {
55
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
56
- w.WriteHeader(http.StatusNotFound)
57
- w.Write([]byte("Column not found"))
58
- }))
59
- defer server.Close()
60
-
61
- client := testutil.NewTestClient(server.URL, "", "board-123", "test-token")
62
- testApp := &app.App{Client: client}
63
-
64
- cmd := columnShowCmd
65
- cmd.SetContext(testApp.ToContext(context.Background()))
66
-
67
- err := handleShowColumnDetails(cmd, "nonexistent-col")
68
- if err == nil {
69
- t.Errorf("expected error for column not found")
70
- }
71
- if err.Error() != "fetching column: unexpected status code 404: Column not found" {
72
- t.Errorf("expected column not found error, got %v", err)
73
- }
74
- }
75
-
76
- func TestColumnShowCommandAPIError(t *testing.T) {
77
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
78
- w.WriteHeader(http.StatusInternalServerError)
79
- w.Write([]byte("Internal Server Error"))
80
- }))
81
- defer server.Close()
82
-
83
- client := testutil.NewTestClient(server.URL, "", "board-123", "test-token")
84
- testApp := &app.App{Client: client}
85
-
86
- cmd := columnShowCmd
87
- cmd.SetContext(testApp.ToContext(context.Background()))
88
-
89
- err := handleShowColumnDetails(cmd, "col-456")
90
- if err == nil {
91
- t.Errorf("expected error for API failure")
92
- }
93
- if err.Error() != "fetching column: unexpected status code 500: Internal Server Error" {
94
- t.Errorf("expected API error, got %v", err)
95
- }
96
- }
97
-
98
- func TestColumnShowCommandNoClient(t *testing.T) {
99
- testApp := &app.App{}
100
-
101
- cmd := columnShowCmd
102
- cmd.SetContext(testApp.ToContext(context.Background()))
103
-
104
- err := handleShowColumnDetails(cmd, "col-456")
105
- if err == nil {
106
- t.Errorf("expected error when client not available")
107
- }
108
- if err.Error() != "API client not available" {
109
- t.Errorf("expected 'client not available' error, got %v", err)
110
- }
111
- }