fizzy-cli 0.8.0 → 0.9.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.
- package/package.json +2 -1
- package/.env +0 -1
- package/.github/workflows/release.yml +0 -29
- package/.github/workflows/tests.yml +0 -24
- package/AGENTS.md +0 -33
- package/CHANGELOG.md +0 -194
- package/Makefile +0 -43
- package/bin/fizzy +0 -0
- package/cmd/account.go +0 -14
- package/cmd/account_list.go +0 -44
- package/cmd/account_list_test.go +0 -118
- package/cmd/board.go +0 -49
- package/cmd/board_create.go +0 -59
- package/cmd/board_create_test.go +0 -141
- package/cmd/board_delete.go +0 -40
- package/cmd/board_delete_test.go +0 -121
- package/cmd/board_list.go +0 -44
- package/cmd/board_list_test.go +0 -115
- package/cmd/board_show.go +0 -40
- package/cmd/board_show_test.go +0 -113
- package/cmd/board_test.go +0 -92
- package/cmd/board_update.go +0 -72
- package/cmd/board_update_test.go +0 -233
- package/cmd/card.go +0 -24
- package/cmd/card_assign.go +0 -55
- package/cmd/card_assign_test.go +0 -130
- package/cmd/card_close.go +0 -46
- package/cmd/card_close_test.go +0 -92
- package/cmd/card_create.go +0 -72
- package/cmd/card_create_test.go +0 -186
- package/cmd/card_delete.go +0 -46
- package/cmd/card_delete_test.go +0 -92
- package/cmd/card_golden.go +0 -46
- package/cmd/card_golden_test.go +0 -92
- package/cmd/card_list.go +0 -114
- package/cmd/card_list_test.go +0 -373
- package/cmd/card_not_now.go +0 -46
- package/cmd/card_not_now_test.go +0 -92
- package/cmd/card_reaction.go +0 -13
- package/cmd/card_reaction_create.go +0 -46
- package/cmd/card_reaction_create_test.go +0 -148
- package/cmd/card_reaction_delete.go +0 -46
- package/cmd/card_reaction_delete_test.go +0 -112
- package/cmd/card_reaction_list.go +0 -51
- package/cmd/card_reaction_list_test.go +0 -127
- package/cmd/card_reopen.go +0 -46
- package/cmd/card_reopen_test.go +0 -92
- package/cmd/card_show.go +0 -46
- package/cmd/card_show_test.go +0 -92
- package/cmd/card_tag.go +0 -51
- package/cmd/card_tag_test.go +0 -112
- package/cmd/card_triage.go +0 -46
- package/cmd/card_ungolden.go +0 -46
- package/cmd/card_ungolden_test.go +0 -92
- package/cmd/card_untriage.go +0 -46
- package/cmd/card_untriage_test.go +0 -92
- package/cmd/card_unwatch.go +0 -46
- package/cmd/card_unwatch_test.go +0 -92
- package/cmd/card_update.go +0 -82
- package/cmd/card_update_test.go +0 -149
- package/cmd/card_watch.go +0 -46
- package/cmd/card_watch_test.go +0 -92
- package/cmd/column.go +0 -14
- package/cmd/column_create.go +0 -79
- package/cmd/column_create_test.go +0 -178
- package/cmd/column_delete.go +0 -40
- package/cmd/column_delete_test.go +0 -121
- package/cmd/column_list.go +0 -44
- package/cmd/column_list_test.go +0 -138
- package/cmd/column_show.go +0 -40
- package/cmd/column_show_test.go +0 -111
- package/cmd/column_update.go +0 -67
- package/cmd/column_update_test.go +0 -198
- package/cmd/comment.go +0 -14
- package/cmd/comment_create.go +0 -51
- package/cmd/comment_create_test.go +0 -129
- package/cmd/comment_delete.go +0 -46
- package/cmd/comment_delete_test.go +0 -92
- package/cmd/comment_list.go +0 -51
- package/cmd/comment_list_test.go +0 -132
- package/cmd/comment_show.go +0 -46
- package/cmd/comment_show_test.go +0 -104
- package/cmd/comment_update.go +0 -51
- package/cmd/comment_update_test.go +0 -130
- package/cmd/login.go +0 -81
- package/cmd/login_test.go +0 -98
- package/cmd/notification.go +0 -14
- package/cmd/notification_list.go +0 -69
- package/cmd/notification_list_test.go +0 -288
- package/cmd/notification_read.go +0 -51
- package/cmd/notification_read_all.go +0 -38
- package/cmd/notification_read_all_test.go +0 -75
- package/cmd/notification_read_test.go +0 -138
- package/cmd/notification_unread.go +0 -44
- package/cmd/notification_unread_test.go +0 -99
- package/cmd/reaction.go +0 -13
- package/cmd/reaction_create.go +0 -46
- package/cmd/reaction_create_test.go +0 -113
- package/cmd/reaction_delete.go +0 -46
- package/cmd/reaction_delete_test.go +0 -92
- package/cmd/reaction_list.go +0 -51
- package/cmd/reaction_list_test.go +0 -125
- package/cmd/root.go +0 -38
- package/cmd/step.go +0 -14
- package/cmd/step_create.go +0 -53
- package/cmd/step_create_test.go +0 -171
- package/cmd/step_delete.go +0 -46
- package/cmd/step_delete_test.go +0 -92
- package/cmd/step_update.go +0 -66
- package/cmd/step_update_test.go +0 -190
- package/cmd/tag.go +0 -15
- package/cmd/tag_list.go +0 -47
- package/cmd/tag_list_test.go +0 -109
- package/cmd/use.go +0 -85
- package/cmd/use_test.go +0 -186
- package/cmd/user.go +0 -22
- package/cmd/user_deactivate.go +0 -40
- package/cmd/user_deactivate_test.go +0 -121
- package/cmd/user_list.go +0 -44
- package/cmd/user_list_test.go +0 -126
- package/cmd/user_show.go +0 -40
- package/cmd/user_show_test.go +0 -110
- package/cmd/user_update.go +0 -71
- package/cmd/user_update_test.go +0 -177
- package/go.mod +0 -31
- package/go.sum +0 -53
- package/internal/api/boards.go +0 -93
- package/internal/api/cards.go +0 -322
- package/internal/api/client.go +0 -99
- package/internal/api/columns.go +0 -113
- package/internal/api/comments.go +0 -108
- package/internal/api/identity.go +0 -24
- package/internal/api/notifications.go +0 -89
- package/internal/api/reactions.go +0 -130
- package/internal/api/steps.go +0 -101
- package/internal/api/tags.go +0 -24
- package/internal/api/types.go +0 -195
- package/internal/api/users.go +0 -75
- package/internal/app/app.go +0 -49
- package/internal/colors/colors.go +0 -32
- package/internal/config/config.go +0 -70
- package/internal/testutil/client.go +0 -26
- package/internal/ui/account_list.go +0 -14
- package/internal/ui/account_selector.go +0 -63
- package/internal/ui/board_list.go +0 -14
- package/internal/ui/board_show.go +0 -17
- package/internal/ui/card_list.go +0 -14
- package/internal/ui/card_show.go +0 -23
- package/internal/ui/column_list.go +0 -28
- package/internal/ui/column_show.go +0 -16
- package/internal/ui/comment_list.go +0 -25
- package/internal/ui/format.go +0 -27
- package/internal/ui/notification_list.go +0 -27
- package/internal/ui/reaction_list.go +0 -14
- package/internal/ui/user_list.go +0 -19
- package/internal/ui/user_show.go +0 -23
|
@@ -1,99 +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 TestNotificationUnreadCommand(t *testing.T) {
|
|
14
|
-
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
15
|
-
if r.URL.Path != "/notifications/notif-123/reading" {
|
|
16
|
-
t.Errorf("expected /notifications/notif-123/reading, 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, "", "", "test-token")
|
|
32
|
-
testApp := &app.App{Client: client}
|
|
33
|
-
|
|
34
|
-
cmd := notificationUnreadCmd
|
|
35
|
-
cmd.SetContext(testApp.ToContext(context.Background()))
|
|
36
|
-
|
|
37
|
-
if err := handleUnreadNotification(cmd, "notif-123"); err != nil {
|
|
38
|
-
t.Fatalf("handleUnreadNotification failed: %v", err)
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
func TestNotificationUnreadCommandNotFound(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("Notification not found"))
|
|
46
|
-
}))
|
|
47
|
-
defer server.Close()
|
|
48
|
-
|
|
49
|
-
client := testutil.NewTestClient(server.URL, "", "", "test-token")
|
|
50
|
-
testApp := &app.App{Client: client}
|
|
51
|
-
|
|
52
|
-
cmd := notificationUnreadCmd
|
|
53
|
-
cmd.SetContext(testApp.ToContext(context.Background()))
|
|
54
|
-
|
|
55
|
-
err := handleUnreadNotification(cmd, "notif-invalid")
|
|
56
|
-
if err == nil {
|
|
57
|
-
t.Errorf("expected error for invalid notification")
|
|
58
|
-
}
|
|
59
|
-
if err.Error() != "notification not found" {
|
|
60
|
-
t.Errorf("expected 'notification not found' error, got %v", err)
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
func TestNotificationUnreadCommandAPIError(t *testing.T) {
|
|
65
|
-
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
66
|
-
w.WriteHeader(http.StatusInternalServerError)
|
|
67
|
-
w.Write([]byte("Internal Server Error"))
|
|
68
|
-
}))
|
|
69
|
-
defer server.Close()
|
|
70
|
-
|
|
71
|
-
client := testutil.NewTestClient(server.URL, "", "", "test-token")
|
|
72
|
-
testApp := &app.App{Client: client}
|
|
73
|
-
|
|
74
|
-
cmd := notificationUnreadCmd
|
|
75
|
-
cmd.SetContext(testApp.ToContext(context.Background()))
|
|
76
|
-
|
|
77
|
-
err := handleUnreadNotification(cmd, "notif-123")
|
|
78
|
-
if err == nil {
|
|
79
|
-
t.Errorf("expected error for API failure")
|
|
80
|
-
}
|
|
81
|
-
if err.Error() != "marking notification as unread: unexpected status code 500: Internal Server Error" {
|
|
82
|
-
t.Errorf("expected API error, got %v", err)
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
func TestNotificationUnreadCommandNoClient(t *testing.T) {
|
|
87
|
-
testApp := &app.App{}
|
|
88
|
-
|
|
89
|
-
cmd := notificationUnreadCmd
|
|
90
|
-
cmd.SetContext(testApp.ToContext(context.Background()))
|
|
91
|
-
|
|
92
|
-
err := handleUnreadNotification(cmd, "notif-123")
|
|
93
|
-
if err == nil {
|
|
94
|
-
t.Errorf("expected error when client not available")
|
|
95
|
-
}
|
|
96
|
-
if err.Error() != "API client not available" {
|
|
97
|
-
t.Errorf("expected 'client not available' error, got %v", err)
|
|
98
|
-
}
|
|
99
|
-
}
|
package/cmd/reaction.go
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
package cmd
|
|
2
|
-
|
|
3
|
-
import "github.com/spf13/cobra"
|
|
4
|
-
|
|
5
|
-
var reactionCmd = &cobra.Command{
|
|
6
|
-
Use: "reaction",
|
|
7
|
-
Short: "Manage reactions",
|
|
8
|
-
Long: `Manage reactions on cards and comments in Fizzy`,
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
func init() {
|
|
12
|
-
rootCmd.AddCommand(reactionCmd)
|
|
13
|
-
}
|
package/cmd/reaction_create.go
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
package cmd
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"context"
|
|
5
|
-
"fmt"
|
|
6
|
-
"strconv"
|
|
7
|
-
|
|
8
|
-
"github.com/rogeriopvl/fizzy/internal/app"
|
|
9
|
-
"github.com/spf13/cobra"
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
var reactionCreateCmd = &cobra.Command{
|
|
13
|
-
Use: "create <card_number> <comment_id> <emoji>",
|
|
14
|
-
Short: "Create a reaction on a comment",
|
|
15
|
-
Long: `Create an emoji reaction on a comment`,
|
|
16
|
-
Args: cobra.ExactArgs(3),
|
|
17
|
-
Run: func(cmd *cobra.Command, args []string) {
|
|
18
|
-
if err := handleCreateReaction(cmd, args[0], args[1], args[2]); err != nil {
|
|
19
|
-
fmt.Fprintf(cmd.OutOrStderr(), "Error: %v\n", err)
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
func handleCreateReaction(cmd *cobra.Command, cardNumber, commentID, emoji string) error {
|
|
25
|
-
cardNum, err := strconv.Atoi(cardNumber)
|
|
26
|
-
if err != nil {
|
|
27
|
-
return fmt.Errorf("invalid card number: %w", err)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
a := app.FromContext(cmd.Context())
|
|
31
|
-
if a == nil || a.Client == nil {
|
|
32
|
-
return fmt.Errorf("API client not available")
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
_, err = a.Client.PostCommentReaction(context.Background(), cardNum, commentID, emoji)
|
|
36
|
-
if err != nil {
|
|
37
|
-
return fmt.Errorf("creating reaction: %w", err)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
fmt.Fprintf(cmd.OutOrStdout(), "✓ Reaction %s created successfully\n", emoji)
|
|
41
|
-
return nil
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
func init() {
|
|
45
|
-
reactionCmd.AddCommand(reactionCreateCmd)
|
|
46
|
-
}
|
|
@@ -1,113 +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 TestReactionCreateCommandSuccess(t *testing.T) {
|
|
17
|
-
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
18
|
-
if r.URL.Path != "/cards/123/comments/comment-456/reactions" {
|
|
19
|
-
t.Errorf("expected /cards/123/comments/comment-456/reactions, 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
|
-
body, _ := io.ReadAll(r.Body)
|
|
31
|
-
var payload map[string]map[string]string
|
|
32
|
-
if err := json.Unmarshal(body, &payload); err != nil {
|
|
33
|
-
t.Fatalf("failed to unmarshal request body: %v", err)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
reactionPayload := payload["reaction"]
|
|
37
|
-
if reactionPayload["content"] != "👍" {
|
|
38
|
-
t.Errorf("expected content '👍', got %s", reactionPayload["content"])
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
w.Header().Set("Content-Type", "application/json")
|
|
42
|
-
w.WriteHeader(http.StatusCreated)
|
|
43
|
-
response := api.Reaction{
|
|
44
|
-
ID: "reaction-789",
|
|
45
|
-
Content: "👍",
|
|
46
|
-
Reacter: api.User{ID: "user-1", Name: "John Doe"},
|
|
47
|
-
}
|
|
48
|
-
json.NewEncoder(w).Encode(response)
|
|
49
|
-
}))
|
|
50
|
-
defer server.Close()
|
|
51
|
-
|
|
52
|
-
client := testutil.NewTestClient(server.URL, "", "", "test-token")
|
|
53
|
-
testApp := &app.App{Client: client}
|
|
54
|
-
|
|
55
|
-
cmd := reactionCreateCmd
|
|
56
|
-
cmd.SetContext(testApp.ToContext(context.Background()))
|
|
57
|
-
|
|
58
|
-
if err := handleCreateReaction(cmd, "123", "comment-456", "👍"); err != nil {
|
|
59
|
-
t.Fatalf("handleCreateReaction failed: %v", err)
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
func TestReactionCreateCommandInvalidCardNumber(t *testing.T) {
|
|
64
|
-
testApp := &app.App{}
|
|
65
|
-
|
|
66
|
-
cmd := reactionCreateCmd
|
|
67
|
-
cmd.SetContext(testApp.ToContext(context.Background()))
|
|
68
|
-
|
|
69
|
-
err := handleCreateReaction(cmd, "not-a-number", "comment-456", "👍")
|
|
70
|
-
if err == nil {
|
|
71
|
-
t.Errorf("expected error for invalid card number")
|
|
72
|
-
}
|
|
73
|
-
if err.Error() != "invalid card number: strconv.Atoi: parsing \"not-a-number\": invalid syntax" {
|
|
74
|
-
t.Errorf("expected invalid card number error, got %v", err)
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
func TestReactionCreateCommandNoClient(t *testing.T) {
|
|
79
|
-
testApp := &app.App{}
|
|
80
|
-
|
|
81
|
-
cmd := reactionCreateCmd
|
|
82
|
-
cmd.SetContext(testApp.ToContext(context.Background()))
|
|
83
|
-
|
|
84
|
-
err := handleCreateReaction(cmd, "123", "comment-456", "👍")
|
|
85
|
-
if err == nil {
|
|
86
|
-
t.Errorf("expected error when client not available")
|
|
87
|
-
}
|
|
88
|
-
if err.Error() != "API client not available" {
|
|
89
|
-
t.Errorf("expected 'client not available' error, got %v", err)
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
func TestReactionCreateCommandAPIError(t *testing.T) {
|
|
94
|
-
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
95
|
-
w.WriteHeader(http.StatusNotFound)
|
|
96
|
-
w.Write([]byte("Comment not found"))
|
|
97
|
-
}))
|
|
98
|
-
defer server.Close()
|
|
99
|
-
|
|
100
|
-
client := testutil.NewTestClient(server.URL, "", "", "test-token")
|
|
101
|
-
testApp := &app.App{Client: client}
|
|
102
|
-
|
|
103
|
-
cmd := reactionCreateCmd
|
|
104
|
-
cmd.SetContext(testApp.ToContext(context.Background()))
|
|
105
|
-
|
|
106
|
-
err := handleCreateReaction(cmd, "123", "comment-456", "👍")
|
|
107
|
-
if err == nil {
|
|
108
|
-
t.Errorf("expected error for API failure")
|
|
109
|
-
}
|
|
110
|
-
if err.Error() != "creating reaction: unexpected status code 404: Comment not found" {
|
|
111
|
-
t.Errorf("expected API error, got %v", err)
|
|
112
|
-
}
|
|
113
|
-
}
|
package/cmd/reaction_delete.go
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
package cmd
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"context"
|
|
5
|
-
"fmt"
|
|
6
|
-
"strconv"
|
|
7
|
-
|
|
8
|
-
"github.com/rogeriopvl/fizzy/internal/app"
|
|
9
|
-
"github.com/spf13/cobra"
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
var reactionDeleteCmd = &cobra.Command{
|
|
13
|
-
Use: "delete <card_number> <comment_id> <reaction_id>",
|
|
14
|
-
Short: "Delete a reaction from a comment",
|
|
15
|
-
Long: `Delete an emoji reaction from a comment`,
|
|
16
|
-
Args: cobra.ExactArgs(3),
|
|
17
|
-
Run: func(cmd *cobra.Command, args []string) {
|
|
18
|
-
if err := handleDeleteReaction(cmd, args[0], args[1], args[2]); err != nil {
|
|
19
|
-
fmt.Fprintf(cmd.OutOrStderr(), "Error: %v\n", err)
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
func handleDeleteReaction(cmd *cobra.Command, cardNumber, commentID, reactionID string) error {
|
|
25
|
-
cardNum, err := strconv.Atoi(cardNumber)
|
|
26
|
-
if err != nil {
|
|
27
|
-
return fmt.Errorf("invalid card number: %w", err)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
a := app.FromContext(cmd.Context())
|
|
31
|
-
if a == nil || a.Client == nil {
|
|
32
|
-
return fmt.Errorf("API client not available")
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
_, err = a.Client.DeleteCommentReaction(context.Background(), cardNum, commentID, reactionID)
|
|
36
|
-
if err != nil {
|
|
37
|
-
return fmt.Errorf("deleting reaction: %w", err)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
fmt.Fprintf(cmd.OutOrStdout(), "✓ Reaction deleted successfully\n")
|
|
41
|
-
return nil
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
func init() {
|
|
45
|
-
reactionCmd.AddCommand(reactionDeleteCmd)
|
|
46
|
-
}
|
|
@@ -1,92 +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 TestReactionDeleteCommandSuccess(t *testing.T) {
|
|
14
|
-
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
15
|
-
if r.URL.Path != "/cards/123/comments/comment-456/reactions/reaction-789" {
|
|
16
|
-
t.Errorf("expected /cards/123/comments/comment-456/reactions/reaction-789, 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, "", "", "test-token")
|
|
32
|
-
testApp := &app.App{Client: client}
|
|
33
|
-
|
|
34
|
-
cmd := reactionDeleteCmd
|
|
35
|
-
cmd.SetContext(testApp.ToContext(context.Background()))
|
|
36
|
-
|
|
37
|
-
if err := handleDeleteReaction(cmd, "123", "comment-456", "reaction-789"); err != nil {
|
|
38
|
-
t.Fatalf("handleDeleteReaction failed: %v", err)
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
func TestReactionDeleteCommandInvalidCardNumber(t *testing.T) {
|
|
43
|
-
testApp := &app.App{}
|
|
44
|
-
|
|
45
|
-
cmd := reactionDeleteCmd
|
|
46
|
-
cmd.SetContext(testApp.ToContext(context.Background()))
|
|
47
|
-
|
|
48
|
-
err := handleDeleteReaction(cmd, "not-a-number", "comment-456", "reaction-789")
|
|
49
|
-
if err == nil {
|
|
50
|
-
t.Errorf("expected error for invalid card number")
|
|
51
|
-
}
|
|
52
|
-
if err.Error() != "invalid card number: strconv.Atoi: parsing \"not-a-number\": invalid syntax" {
|
|
53
|
-
t.Errorf("expected invalid card number error, got %v", err)
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
func TestReactionDeleteCommandNoClient(t *testing.T) {
|
|
58
|
-
testApp := &app.App{}
|
|
59
|
-
|
|
60
|
-
cmd := reactionDeleteCmd
|
|
61
|
-
cmd.SetContext(testApp.ToContext(context.Background()))
|
|
62
|
-
|
|
63
|
-
err := handleDeleteReaction(cmd, "123", "comment-456", "reaction-789")
|
|
64
|
-
if err == nil {
|
|
65
|
-
t.Errorf("expected error when client not available")
|
|
66
|
-
}
|
|
67
|
-
if err.Error() != "API client not available" {
|
|
68
|
-
t.Errorf("expected 'client not available' error, got %v", err)
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
func TestReactionDeleteCommandAPIError(t *testing.T) {
|
|
73
|
-
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
74
|
-
w.WriteHeader(http.StatusNotFound)
|
|
75
|
-
w.Write([]byte("Reaction not found"))
|
|
76
|
-
}))
|
|
77
|
-
defer server.Close()
|
|
78
|
-
|
|
79
|
-
client := testutil.NewTestClient(server.URL, "", "", "test-token")
|
|
80
|
-
testApp := &app.App{Client: client}
|
|
81
|
-
|
|
82
|
-
cmd := reactionDeleteCmd
|
|
83
|
-
cmd.SetContext(testApp.ToContext(context.Background()))
|
|
84
|
-
|
|
85
|
-
err := handleDeleteReaction(cmd, "123", "comment-456", "reaction-789")
|
|
86
|
-
if err == nil {
|
|
87
|
-
t.Errorf("expected error for API failure")
|
|
88
|
-
}
|
|
89
|
-
if err.Error() != "deleting reaction: unexpected status code 404: Reaction not found" {
|
|
90
|
-
t.Errorf("expected API error, got %v", err)
|
|
91
|
-
}
|
|
92
|
-
}
|
package/cmd/reaction_list.go
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
package cmd
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"context"
|
|
5
|
-
"fmt"
|
|
6
|
-
"strconv"
|
|
7
|
-
|
|
8
|
-
"github.com/rogeriopvl/fizzy/internal/app"
|
|
9
|
-
"github.com/rogeriopvl/fizzy/internal/ui"
|
|
10
|
-
"github.com/spf13/cobra"
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
var reactionListCmd = &cobra.Command{
|
|
14
|
-
Use: "list <card_number> <comment_id>",
|
|
15
|
-
Short: "List reactions on a comment",
|
|
16
|
-
Long: `Retrieve and display all reactions on a comment`,
|
|
17
|
-
Args: cobra.ExactArgs(2),
|
|
18
|
-
Run: func(cmd *cobra.Command, args []string) {
|
|
19
|
-
if err := handleListReactions(cmd, args[0], args[1]); err != nil {
|
|
20
|
-
fmt.Fprintf(cmd.OutOrStderr(), "Error: %v\n", err)
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
func handleListReactions(cmd *cobra.Command, cardNumber, commentID string) error {
|
|
26
|
-
cardNum, err := strconv.Atoi(cardNumber)
|
|
27
|
-
if err != nil {
|
|
28
|
-
return fmt.Errorf("invalid card number: %w", err)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
a := app.FromContext(cmd.Context())
|
|
32
|
-
if a == nil || a.Client == nil {
|
|
33
|
-
return fmt.Errorf("API client not available")
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
reactions, err := a.Client.GetCommentReactions(context.Background(), cardNum, commentID)
|
|
37
|
-
if err != nil {
|
|
38
|
-
return fmt.Errorf("fetching reactions: %w", err)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if len(reactions) == 0 {
|
|
42
|
-
fmt.Println("No reactions found")
|
|
43
|
-
return nil
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return ui.DisplayReactions(reactions)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
func init() {
|
|
50
|
-
reactionCmd.AddCommand(reactionListCmd)
|
|
51
|
-
}
|
|
@@ -1,125 +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 TestReactionListCommandSuccess(t *testing.T) {
|
|
16
|
-
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
17
|
-
if r.URL.Path != "/cards/123/comments/comment-456/reactions" {
|
|
18
|
-
t.Errorf("expected /cards/123/comments/comment-456/reactions, 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.Reaction{
|
|
31
|
-
{
|
|
32
|
-
ID: "reaction-1",
|
|
33
|
-
Content: "👍",
|
|
34
|
-
Reacter: api.User{ID: "user-1", Name: "John Doe"},
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
ID: "reaction-2",
|
|
38
|
-
Content: "❤️",
|
|
39
|
-
Reacter: api.User{ID: "user-2", Name: "Jane Doe"},
|
|
40
|
-
},
|
|
41
|
-
}
|
|
42
|
-
json.NewEncoder(w).Encode(response)
|
|
43
|
-
}))
|
|
44
|
-
defer server.Close()
|
|
45
|
-
|
|
46
|
-
client := testutil.NewTestClient(server.URL, "", "", "test-token")
|
|
47
|
-
testApp := &app.App{Client: client}
|
|
48
|
-
|
|
49
|
-
cmd := reactionListCmd
|
|
50
|
-
cmd.SetContext(testApp.ToContext(context.Background()))
|
|
51
|
-
|
|
52
|
-
if err := handleListReactions(cmd, "123", "comment-456"); err != nil {
|
|
53
|
-
t.Fatalf("handleListReactions failed: %v", err)
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
func TestReactionListCommandNoReactions(t *testing.T) {
|
|
58
|
-
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
59
|
-
w.Header().Set("Content-Type", "application/json")
|
|
60
|
-
json.NewEncoder(w).Encode([]api.Reaction{})
|
|
61
|
-
}))
|
|
62
|
-
defer server.Close()
|
|
63
|
-
|
|
64
|
-
client := testutil.NewTestClient(server.URL, "", "", "test-token")
|
|
65
|
-
testApp := &app.App{Client: client}
|
|
66
|
-
|
|
67
|
-
cmd := reactionListCmd
|
|
68
|
-
cmd.SetContext(testApp.ToContext(context.Background()))
|
|
69
|
-
|
|
70
|
-
if err := handleListReactions(cmd, "123", "comment-456"); err != nil {
|
|
71
|
-
t.Fatalf("handleListReactions failed: %v", err)
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
func TestReactionListCommandInvalidCardNumber(t *testing.T) {
|
|
76
|
-
testApp := &app.App{}
|
|
77
|
-
|
|
78
|
-
cmd := reactionListCmd
|
|
79
|
-
cmd.SetContext(testApp.ToContext(context.Background()))
|
|
80
|
-
|
|
81
|
-
err := handleListReactions(cmd, "not-a-number", "comment-456")
|
|
82
|
-
if err == nil {
|
|
83
|
-
t.Errorf("expected error for invalid card number")
|
|
84
|
-
}
|
|
85
|
-
if err.Error() != "invalid card number: strconv.Atoi: parsing \"not-a-number\": invalid syntax" {
|
|
86
|
-
t.Errorf("expected invalid card number error, got %v", err)
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
func TestReactionListCommandNoClient(t *testing.T) {
|
|
91
|
-
testApp := &app.App{}
|
|
92
|
-
|
|
93
|
-
cmd := reactionListCmd
|
|
94
|
-
cmd.SetContext(testApp.ToContext(context.Background()))
|
|
95
|
-
|
|
96
|
-
err := handleListReactions(cmd, "123", "comment-456")
|
|
97
|
-
if err == nil {
|
|
98
|
-
t.Errorf("expected error when client not available")
|
|
99
|
-
}
|
|
100
|
-
if err.Error() != "API client not available" {
|
|
101
|
-
t.Errorf("expected 'client not available' error, got %v", err)
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
func TestReactionListCommandAPIError(t *testing.T) {
|
|
106
|
-
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
107
|
-
w.WriteHeader(http.StatusNotFound)
|
|
108
|
-
w.Write([]byte("Comment not found"))
|
|
109
|
-
}))
|
|
110
|
-
defer server.Close()
|
|
111
|
-
|
|
112
|
-
client := testutil.NewTestClient(server.URL, "", "", "test-token")
|
|
113
|
-
testApp := &app.App{Client: client}
|
|
114
|
-
|
|
115
|
-
cmd := reactionListCmd
|
|
116
|
-
cmd.SetContext(testApp.ToContext(context.Background()))
|
|
117
|
-
|
|
118
|
-
err := handleListReactions(cmd, "123", "comment-456")
|
|
119
|
-
if err == nil {
|
|
120
|
-
t.Errorf("expected error for API failure")
|
|
121
|
-
}
|
|
122
|
-
if err.Error() != "fetching reactions: unexpected status code 404: Comment not found" {
|
|
123
|
-
t.Errorf("expected API error, got %v", err)
|
|
124
|
-
}
|
|
125
|
-
}
|
package/cmd/root.go
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
package cmd
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"fmt"
|
|
5
|
-
"os"
|
|
6
|
-
|
|
7
|
-
"github.com/rogeriopvl/fizzy/internal/app"
|
|
8
|
-
"github.com/spf13/cobra"
|
|
9
|
-
)
|
|
10
|
-
|
|
11
|
-
var Version = "dev"
|
|
12
|
-
|
|
13
|
-
var rootCmd = &cobra.Command{
|
|
14
|
-
Use: "fizzy-cli",
|
|
15
|
-
Short: "Fizzy CLI",
|
|
16
|
-
Long: `Fizzy CLI`,
|
|
17
|
-
Version: Version,
|
|
18
|
-
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
|
19
|
-
a, _ := app.New()
|
|
20
|
-
if a != nil {
|
|
21
|
-
cmd.SetContext(a.ToContext(cmd.Context()))
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
func Execute() {
|
|
27
|
-
err := rootCmd.Execute()
|
|
28
|
-
if err != nil {
|
|
29
|
-
os.Exit(1)
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
func init() {
|
|
34
|
-
// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.fizzy-cli.yaml)")
|
|
35
|
-
|
|
36
|
-
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
|
37
|
-
rootCmd.SetVersionTemplate(fmt.Sprintf("fizzy-cli v%s\n", Version))
|
|
38
|
-
}
|
package/cmd/step.go
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
// Package cmd
|
|
2
|
-
package cmd
|
|
3
|
-
|
|
4
|
-
import "github.com/spf13/cobra"
|
|
5
|
-
|
|
6
|
-
var stepCmd = &cobra.Command{
|
|
7
|
-
Use: "step",
|
|
8
|
-
Short: "Manage card steps",
|
|
9
|
-
Long: `Manage steps (to-do items) on cards in Fizzy`,
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
func init() {
|
|
13
|
-
rootCmd.AddCommand(stepCmd)
|
|
14
|
-
}
|
package/cmd/step_create.go
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
package cmd
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"context"
|
|
5
|
-
"fmt"
|
|
6
|
-
"strconv"
|
|
7
|
-
|
|
8
|
-
"github.com/rogeriopvl/fizzy/internal/app"
|
|
9
|
-
"github.com/spf13/cobra"
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
var stepCreateCmd = &cobra.Command{
|
|
13
|
-
Use: "create <card_number>",
|
|
14
|
-
Short: "Create a new step",
|
|
15
|
-
Long: `Create a new step (to-do item) on a card`,
|
|
16
|
-
Args: cobra.ExactArgs(1),
|
|
17
|
-
Run: func(cmd *cobra.Command, args []string) {
|
|
18
|
-
if err := handleCreateStep(cmd, args[0]); err != nil {
|
|
19
|
-
fmt.Fprintf(cmd.OutOrStderr(), "Error: %v\n", err)
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
func handleCreateStep(cmd *cobra.Command, cardNumber string) error {
|
|
25
|
-
cardNum, err := strconv.Atoi(cardNumber)
|
|
26
|
-
if err != nil {
|
|
27
|
-
return fmt.Errorf("invalid card number: %w", err)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
a := app.FromContext(cmd.Context())
|
|
31
|
-
if a == nil || a.Client == nil {
|
|
32
|
-
return fmt.Errorf("API client not available")
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
content, _ := cmd.Flags().GetString("content")
|
|
36
|
-
completed, _ := cmd.Flags().GetBool("completed")
|
|
37
|
-
|
|
38
|
-
_, err = a.Client.PostCardStep(context.Background(), cardNum, content, completed)
|
|
39
|
-
if err != nil {
|
|
40
|
-
return fmt.Errorf("creating step: %w", err)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
fmt.Fprintf(cmd.OutOrStdout(), "✓ Step created successfully\n")
|
|
44
|
-
return nil
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
func init() {
|
|
48
|
-
stepCreateCmd.Flags().StringP("content", "c", "", "Step content (required)")
|
|
49
|
-
stepCreateCmd.MarkFlagRequired("content")
|
|
50
|
-
stepCreateCmd.Flags().BoolP("completed", "d", false, "Mark step as completed")
|
|
51
|
-
|
|
52
|
-
stepCmd.AddCommand(stepCreateCmd)
|
|
53
|
-
}
|