fizzy-cli 0.7.0 → 0.8.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.
@@ -0,0 +1,112 @@
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 TestCardReactionDeleteCommandSuccess(t *testing.T) {
14
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
15
+ if r.URL.Path != "/cards/123/reactions/reaction-456" {
16
+ t.Errorf("expected /cards/123/reactions/reaction-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, "", "", "test-token")
32
+ testApp := &app.App{Client: client}
33
+
34
+ cmd := cardReactionDeleteCmd
35
+ cmd.SetContext(testApp.ToContext(context.Background()))
36
+
37
+ if err := handleDeleteCardReaction(cmd, "123", "reaction-456"); err != nil {
38
+ t.Fatalf("handleDeleteCardReaction failed: %v", err)
39
+ }
40
+ }
41
+
42
+ func TestCardReactionDeleteCommandInvalidCardNumber(t *testing.T) {
43
+ testApp := &app.App{}
44
+
45
+ cmd := cardReactionDeleteCmd
46
+ cmd.SetContext(testApp.ToContext(context.Background()))
47
+
48
+ err := handleDeleteCardReaction(cmd, "not-a-number", "reaction-456")
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 TestCardReactionDeleteCommandNoClient(t *testing.T) {
58
+ testApp := &app.App{}
59
+
60
+ cmd := cardReactionDeleteCmd
61
+ cmd.SetContext(testApp.ToContext(context.Background()))
62
+
63
+ err := handleDeleteCardReaction(cmd, "123", "reaction-456")
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 TestCardReactionDeleteCommandAPIError(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 := cardReactionDeleteCmd
83
+ cmd.SetContext(testApp.ToContext(context.Background()))
84
+
85
+ err := handleDeleteCardReaction(cmd, "123", "reaction-456")
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
+ }
93
+
94
+ func TestCardReactionDeleteCommandDifferentReactionID(t *testing.T) {
95
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
96
+ if r.URL.Path != "/cards/456/reactions/reaction-789" {
97
+ t.Errorf("expected /cards/456/reactions/reaction-789, got %s", r.URL.Path)
98
+ }
99
+ w.WriteHeader(http.StatusNoContent)
100
+ }))
101
+ defer server.Close()
102
+
103
+ client := testutil.NewTestClient(server.URL, "", "", "test-token")
104
+ testApp := &app.App{Client: client}
105
+
106
+ cmd := cardReactionDeleteCmd
107
+ cmd.SetContext(testApp.ToContext(context.Background()))
108
+
109
+ if err := handleDeleteCardReaction(cmd, "456", "reaction-789"); err != nil {
110
+ t.Fatalf("handleDeleteCardReaction failed: %v", err)
111
+ }
112
+ }
@@ -0,0 +1,51 @@
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 cardReactionListCmd = &cobra.Command{
14
+ Use: "list <card_number>",
15
+ Short: "List reactions on a card",
16
+ Long: `Retrieve and display all reactions (boosts) on a card`,
17
+ Args: cobra.ExactArgs(1),
18
+ Run: func(cmd *cobra.Command, args []string) {
19
+ if err := handleListCardReactions(cmd, args[0]); err != nil {
20
+ fmt.Fprintf(cmd.OutOrStderr(), "Error: %v\n", err)
21
+ }
22
+ },
23
+ }
24
+
25
+ func handleListCardReactions(cmd *cobra.Command, cardNumber 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.GetCardReactions(context.Background(), cardNum)
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
+ cardReactionCmd.AddCommand(cardReactionListCmd)
51
+ }
@@ -0,0 +1,127 @@
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 TestCardReactionListCommandSuccess(t *testing.T) {
16
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
17
+ if r.URL.Path != "/cards/123/reactions" {
18
+ t.Errorf("expected /cards/123/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
+ w.WriteHeader(http.StatusOK)
31
+ reactions := []api.Reaction{
32
+ {
33
+ ID: "reaction-1",
34
+ Content: "👍",
35
+ Reacter: api.User{ID: "user-1", Name: "Alice"},
36
+ },
37
+ {
38
+ ID: "reaction-2",
39
+ Content: "🎉",
40
+ Reacter: api.User{ID: "user-2", Name: "Bob"},
41
+ },
42
+ }
43
+ json.NewEncoder(w).Encode(reactions)
44
+ }))
45
+ defer server.Close()
46
+
47
+ client := testutil.NewTestClient(server.URL, "", "", "test-token")
48
+ testApp := &app.App{Client: client}
49
+
50
+ cmd := cardReactionListCmd
51
+ cmd.SetContext(testApp.ToContext(context.Background()))
52
+
53
+ if err := handleListCardReactions(cmd, "123"); err != nil {
54
+ t.Fatalf("handleListCardReactions failed: %v", err)
55
+ }
56
+ }
57
+
58
+ func TestCardReactionListCommandNoReactions(t *testing.T) {
59
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
60
+ w.Header().Set("Content-Type", "application/json")
61
+ w.WriteHeader(http.StatusOK)
62
+ json.NewEncoder(w).Encode([]api.Reaction{})
63
+ }))
64
+ defer server.Close()
65
+
66
+ client := testutil.NewTestClient(server.URL, "", "", "test-token")
67
+ testApp := &app.App{Client: client}
68
+
69
+ cmd := cardReactionListCmd
70
+ cmd.SetContext(testApp.ToContext(context.Background()))
71
+
72
+ if err := handleListCardReactions(cmd, "123"); err != nil {
73
+ t.Fatalf("handleListCardReactions failed: %v", err)
74
+ }
75
+ }
76
+
77
+ func TestCardReactionListCommandInvalidCardNumber(t *testing.T) {
78
+ testApp := &app.App{}
79
+
80
+ cmd := cardReactionListCmd
81
+ cmd.SetContext(testApp.ToContext(context.Background()))
82
+
83
+ err := handleListCardReactions(cmd, "not-a-number")
84
+ if err == nil {
85
+ t.Errorf("expected error for invalid card number")
86
+ }
87
+ if err.Error() != "invalid card number: strconv.Atoi: parsing \"not-a-number\": invalid syntax" {
88
+ t.Errorf("expected invalid card number error, got %v", err)
89
+ }
90
+ }
91
+
92
+ func TestCardReactionListCommandNoClient(t *testing.T) {
93
+ testApp := &app.App{}
94
+
95
+ cmd := cardReactionListCmd
96
+ cmd.SetContext(testApp.ToContext(context.Background()))
97
+
98
+ err := handleListCardReactions(cmd, "123")
99
+ if err == nil {
100
+ t.Errorf("expected error when client not available")
101
+ }
102
+ if err.Error() != "API client not available" {
103
+ t.Errorf("expected 'client not available' error, got %v", err)
104
+ }
105
+ }
106
+
107
+ func TestCardReactionListCommandAPIError(t *testing.T) {
108
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
109
+ w.WriteHeader(http.StatusNotFound)
110
+ w.Write([]byte("Card not found"))
111
+ }))
112
+ defer server.Close()
113
+
114
+ client := testutil.NewTestClient(server.URL, "", "", "test-token")
115
+ testApp := &app.App{Client: client}
116
+
117
+ cmd := cardReactionListCmd
118
+ cmd.SetContext(testApp.ToContext(context.Background()))
119
+
120
+ err := handleListCardReactions(cmd, "123")
121
+ if err == nil {
122
+ t.Errorf("expected error for API failure")
123
+ }
124
+ if err.Error() != "fetching reactions: unexpected status code 404: Card not found" {
125
+ t.Errorf("expected API error, got %v", err)
126
+ }
127
+ }
package/cmd/reaction.go CHANGED
@@ -4,8 +4,8 @@ import "github.com/spf13/cobra"
4
4
 
5
5
  var reactionCmd = &cobra.Command{
6
6
  Use: "reaction",
7
- Short: "Manage comment reactions",
8
- Long: `Manage reactions on comments in Fizzy`,
7
+ Short: "Manage reactions",
8
+ Long: `Manage reactions on cards and comments in Fizzy`,
9
9
  }
10
10
 
11
11
  func init() {
package/cmd/user.go ADDED
@@ -0,0 +1,22 @@
1
+ // Package cmd
2
+ package cmd
3
+
4
+ import (
5
+ "github.com/spf13/cobra"
6
+ )
7
+
8
+ var userCmd = &cobra.Command{
9
+ Use: "user",
10
+ Short: "Manage users",
11
+ Long: `Manage users in your account.
12
+
13
+ Use subcommands to list, view, or manage users:
14
+ fizzy user list List all users
15
+ fizzy user show <id> Show user details
16
+ fizzy user update <id> Update user settings
17
+ fizzy user deactivate <id> Deactivate a user`,
18
+ }
19
+
20
+ func init() {
21
+ rootCmd.AddCommand(userCmd)
22
+ }
@@ -0,0 +1,40 @@
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 userDeactivateCmd = &cobra.Command{
12
+ Use: "deactivate <user_id>",
13
+ Short: "Deactivate a user",
14
+ Long: `Deactivate a user. Only account administrators can deactivate users.`,
15
+ Args: cobra.ExactArgs(1),
16
+ Run: func(cmd *cobra.Command, args []string) {
17
+ if err := handleDeactivateUser(cmd, args[0]); err != nil {
18
+ fmt.Fprintf(cmd.OutOrStderr(), "Error: %v\n", err)
19
+ }
20
+ },
21
+ }
22
+
23
+ func handleDeactivateUser(cmd *cobra.Command, userID 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.DeleteUser(context.Background(), userID)
30
+ if err != nil {
31
+ return fmt.Errorf("deactivating user: %w", err)
32
+ }
33
+
34
+ fmt.Fprintf(cmd.OutOrStdout(), "✓ User '%s' deactivated successfully\n", userID)
35
+ return nil
36
+ }
37
+
38
+ func init() {
39
+ userCmd.AddCommand(userDeactivateCmd)
40
+ }
@@ -0,0 +1,121 @@
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 TestUserDeactivateCommandSuccess(t *testing.T) {
14
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
15
+ if r.URL.Path != "/users/user-123" {
16
+ t.Errorf("expected /users/user-123, 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 := userDeactivateCmd
35
+ cmd.SetContext(testApp.ToContext(context.Background()))
36
+
37
+ if err := handleDeactivateUser(cmd, "user-123"); err != nil {
38
+ t.Fatalf("handleDeactivateUser failed: %v", err)
39
+ }
40
+ }
41
+
42
+ func TestUserDeactivateCommandNotFound(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("User 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 := userDeactivateCmd
53
+ cmd.SetContext(testApp.ToContext(context.Background()))
54
+
55
+ err := handleDeactivateUser(cmd, "nonexistent-user")
56
+ if err == nil {
57
+ t.Errorf("expected error for user not found")
58
+ }
59
+ if err.Error() != "deactivating user: unexpected status code 404: User not found" {
60
+ t.Errorf("expected user not found error, got %v", err)
61
+ }
62
+ }
63
+
64
+ func TestUserDeactivateCommandForbidden(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 deactivate this user"))
68
+ }))
69
+ defer server.Close()
70
+
71
+ client := testutil.NewTestClient(server.URL, "", "", "test-token")
72
+ testApp := &app.App{Client: client}
73
+
74
+ cmd := userDeactivateCmd
75
+ cmd.SetContext(testApp.ToContext(context.Background()))
76
+
77
+ err := handleDeactivateUser(cmd, "user-123")
78
+ if err == nil {
79
+ t.Errorf("expected error for forbidden access")
80
+ }
81
+ if err.Error() != "deactivating user: unexpected status code 403: You don't have permission to deactivate this user" {
82
+ t.Errorf("expected permission error, got %v", err)
83
+ }
84
+ }
85
+
86
+ func TestUserDeactivateCommandAPIError(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, "", "", "test-token")
94
+ testApp := &app.App{Client: client}
95
+
96
+ cmd := userDeactivateCmd
97
+ cmd.SetContext(testApp.ToContext(context.Background()))
98
+
99
+ err := handleDeactivateUser(cmd, "user-123")
100
+ if err == nil {
101
+ t.Errorf("expected error for API failure")
102
+ }
103
+ if err.Error() != "deactivating user: unexpected status code 500: Internal Server Error" {
104
+ t.Errorf("expected API error, got %v", err)
105
+ }
106
+ }
107
+
108
+ func TestUserDeactivateCommandNoClient(t *testing.T) {
109
+ testApp := &app.App{}
110
+
111
+ cmd := userDeactivateCmd
112
+ cmd.SetContext(testApp.ToContext(context.Background()))
113
+
114
+ err := handleDeactivateUser(cmd, "user-123")
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
+ }
@@ -0,0 +1,44 @@
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 userListCmd = &cobra.Command{
13
+ Use: "list",
14
+ Short: "List all users",
15
+ Long: `Retrieve and display all users from the current account`,
16
+ Run: func(cmd *cobra.Command, args []string) {
17
+ if err := handleListUsers(cmd); err != nil {
18
+ fmt.Fprintf(cmd.OutOrStderr(), "Error: %v\n", err)
19
+ }
20
+ },
21
+ }
22
+
23
+ func handleListUsers(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
+ users, err := a.Client.GetUsers(context.Background())
30
+ if err != nil {
31
+ return fmt.Errorf("fetching users: %w", err)
32
+ }
33
+
34
+ if len(users) == 0 {
35
+ fmt.Println("No users found")
36
+ return nil
37
+ }
38
+
39
+ return ui.DisplayUsers(cmd.OutOrStdout(), users)
40
+ }
41
+
42
+ func init() {
43
+ userCmd.AddCommand(userListCmd)
44
+ }
@@ -0,0 +1,126 @@
1
+ package cmd
2
+
3
+ import (
4
+ "bytes"
5
+ "context"
6
+ "encoding/json"
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 TestUserListCommand(t *testing.T) {
17
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
18
+ if r.URL.Path != "/users" {
19
+ t.Errorf("expected /users, got %s", r.URL.Path)
20
+ }
21
+ if r.Method != http.MethodGet {
22
+ t.Errorf("expected GET, got %s", r.Method)
23
+ }
24
+
25
+ auth := r.Header.Get("Authorization")
26
+ if auth == "" {
27
+ t.Error("missing Authorization header")
28
+ }
29
+ if auth != "Bearer test-token" {
30
+ t.Errorf("expected Bearer test-token, got %s", auth)
31
+ }
32
+
33
+ w.Header().Set("Content-Type", "application/json")
34
+ response := []api.User{
35
+ {
36
+ ID: "user-123",
37
+ Name: "John Doe",
38
+ Email: "john@example.com",
39
+ Role: "admin",
40
+ Active: true,
41
+ CreatedAt: "2025-01-01T00:00:00Z",
42
+ },
43
+ {
44
+ ID: "user-456",
45
+ Name: "Jane Smith",
46
+ Email: "jane@example.com",
47
+ Role: "member",
48
+ Active: false,
49
+ CreatedAt: "2025-01-02T00:00:00Z",
50
+ },
51
+ }
52
+ json.NewEncoder(w).Encode(response)
53
+ }))
54
+ defer server.Close()
55
+
56
+ client := testutil.NewTestClient(server.URL, "", "", "test-token")
57
+ testApp := &app.App{Client: client}
58
+
59
+ cmd := userListCmd
60
+ cmd.SetContext(testApp.ToContext(context.Background()))
61
+ cmd.SetOut(&bytes.Buffer{})
62
+
63
+ if err := handleListUsers(cmd); err != nil {
64
+ t.Fatalf("handleListUsers failed: %v", err)
65
+ }
66
+ }
67
+
68
+ func TestUserListCommandNoUsers(t *testing.T) {
69
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
70
+ w.Header().Set("Content-Type", "application/json")
71
+ json.NewEncoder(w).Encode([]api.User{})
72
+ }))
73
+ defer server.Close()
74
+
75
+ client := testutil.NewTestClient(server.URL, "", "", "test-token")
76
+ testApp := &app.App{Client: client}
77
+
78
+ cmd := userListCmd
79
+ cmd.SetContext(testApp.ToContext(context.Background()))
80
+ cmd.SetOut(&bytes.Buffer{})
81
+
82
+ if err := handleListUsers(cmd); err != nil {
83
+ t.Fatalf("handleListUsers failed: %v", err)
84
+ }
85
+ }
86
+
87
+ func TestUserListCommandAPIError(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, "", "", "test-token")
95
+ testApp := &app.App{Client: client}
96
+
97
+ cmd := userListCmd
98
+ cmd.SetContext(testApp.ToContext(context.Background()))
99
+
100
+ cmd.SetOut(&bytes.Buffer{})
101
+
102
+ err := handleListUsers(cmd)
103
+ if err == nil {
104
+ t.Errorf("expected error for API failure")
105
+ }
106
+ if err.Error() != "fetching users: unexpected status code 500: Internal Server Error" {
107
+ t.Errorf("expected API error, got %v", err)
108
+ }
109
+ }
110
+
111
+ func TestUserListCommandNoClient(t *testing.T) {
112
+ testApp := &app.App{}
113
+
114
+ cmd := userListCmd
115
+ cmd.SetContext(testApp.ToContext(context.Background()))
116
+
117
+ cmd.SetOut(&bytes.Buffer{})
118
+
119
+ err := handleListUsers(cmd)
120
+ if err == nil {
121
+ t.Errorf("expected error when client not available")
122
+ }
123
+ if err.Error() != "API client not available" {
124
+ t.Errorf("expected 'client not available' error, got %v", err)
125
+ }
126
+ }
@@ -0,0 +1,40 @@
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 userShowCmd = &cobra.Command{
13
+ Use: "show <user_id>",
14
+ Short: "Show user details",
15
+ Long: `Retrieve and display detailed information about a specific user`,
16
+ Args: cobra.ExactArgs(1),
17
+ Run: func(cmd *cobra.Command, args []string) {
18
+ if err := handleShowUser(cmd, args[0]); err != nil {
19
+ fmt.Fprintf(cmd.OutOrStderr(), "Error: %v\n", err)
20
+ }
21
+ },
22
+ }
23
+
24
+ func handleShowUser(cmd *cobra.Command, userID 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
+ user, err := a.Client.GetUser(context.Background(), userID)
31
+ if err != nil {
32
+ return fmt.Errorf("fetching user: %w", err)
33
+ }
34
+
35
+ return ui.DisplayUser(cmd.OutOrStdout(), user)
36
+ }
37
+
38
+ func init() {
39
+ userCmd.AddCommand(userShowCmd)
40
+ }