Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,9 @@ fizzy card untriage 42
# Assign/unassign (toggles)
fizzy card assign 42 --user USER_ID

# Self-assign/unassign (toggles current user)
fizzy card self-assign 42

# Tag/untag (toggles, creates tag if needed)
fizzy card tag 42 --tag "bug"

Expand Down
24 changes: 24 additions & 0 deletions e2e/tests/card_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,30 @@ func TestCardActions(t *testing.T) {
}
})

t.Run("self-assign card", func(t *testing.T) {
result := h.Run("card", "self-assign", cardStr)

if result.ExitCode != harness.ExitSuccess {
t.Errorf("expected exit code %d, got %d\nstderr: %s", harness.ExitSuccess, result.ExitCode, result.Stderr)
}

if !result.Response.Success {
t.Errorf("expected success=true, error: %+v", result.Response.Error)
}
})

t.Run("self-assign card again to unassign", func(t *testing.T) {
result := h.Run("card", "self-assign", cardStr)

if result.ExitCode != harness.ExitSuccess {
t.Errorf("expected exit code %d, got %d\nstderr: %s", harness.ExitSuccess, result.ExitCode, result.Stderr)
}

if !result.Response.Success {
t.Errorf("expected success=true, error: %+v", result.Response.Error)
}
})

t.Run("golden card", func(t *testing.T) {
result := h.Run("card", "golden", cardStr)

Expand Down
33 changes: 33 additions & 0 deletions internal/commands/card.go
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,36 @@ var cardAssignCmd = &cobra.Command{
},
}

var cardSelfAssignCmd = &cobra.Command{
Use: "self-assign CARD_NUMBER",
Short: "Toggle self-assignment on a card",
Long: "Toggles the current user's assignment on a card.",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
if err := requireAuthAndAccount(); err != nil {
exitWithError(err)
}

cardNumber := args[0]

client := getClient()
resp, err := client.Post("/cards/"+cardNumber+"/self_assignment.json", nil)
if err != nil {
exitWithError(err)
}

breadcrumbs := []response.Breadcrumb{
breadcrumb("show", fmt.Sprintf("fizzy card show %s", cardNumber), "View card"),
}

data := resp.Data
if data == nil {
data = map[string]interface{}{}
}
printSuccessWithBreadcrumbs(data, "", breadcrumbs)
},
}

// Card tag flags
var cardTagTag string

Expand Down Expand Up @@ -1081,6 +1111,9 @@ func init() {
cardAssignCmd.Flags().StringVar(&cardAssignUser, "user", "", "User ID (required)")
cardCmd.AddCommand(cardAssignCmd)

// Self-assign
cardCmd.AddCommand(cardSelfAssignCmd)

// Tag
cardTagCmd.Flags().StringVar(&cardTagTag, "tag", "", "Tag name (required)")
cardCmd.AddCommand(cardTagCmd)
Expand Down
25 changes: 25 additions & 0 deletions internal/commands/card_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,31 @@ func TestCardAssign(t *testing.T) {
})
}

func TestCardSelfAssign(t *testing.T) {
t.Run("self-assigns card", func(t *testing.T) {
mock := NewMockClient()
mock.PostResponse = &client.APIResponse{
StatusCode: 200,
Data: map[string]interface{}{},
}

result := SetTestMode(mock)
SetTestConfig("token", "account", "https://api.example.com")
defer ResetTestMode()

RunTestCommand(func() {
cardSelfAssignCmd.Run(cardSelfAssignCmd, []string{"42"})
})

if result.ExitCode != 0 {
t.Errorf("expected exit code 0, got %d", result.ExitCode)
}
if mock.PostCalls[0].Path != "/cards/42/self_assignment.json" {
t.Errorf("expected path '/cards/42/self_assignment.json', got '%s'", mock.PostCalls[0].Path)
}
})
}

func TestCardTag(t *testing.T) {
t.Run("tags card", func(t *testing.T) {
mock := NewMockClient()
Expand Down
6 changes: 5 additions & 1 deletion skills/fizzy/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,7 @@ fizzy card untriage CARD_NUMBER # Remove from column, back to triage
fizzy card column CARD_NUMBER --column ID # Move to column (use column ID or: maybe, not-yet, done)
fizzy card move CARD_NUMBER --to BOARD_ID # Move card to a different board
fizzy card assign CARD_NUMBER --user ID # Toggle user assignment
fizzy card self-assign CARD_NUMBER # Toggle current user's assignment
fizzy card tag CARD_NUMBER --tag "name" # Toggle tag (creates tag if needed)
fizzy card watch CARD_NUMBER # Subscribe to notifications
fizzy card unwatch CARD_NUMBER # Unsubscribe
Expand Down Expand Up @@ -713,7 +714,10 @@ fizzy card create --board BOARD_ID --title "Card" --image "$SIGNED_ID"
# Move to a column
fizzy card column 579 --column maybe

# Assign to user
# Assign to yourself
fizzy card self-assign 579

# Or assign to another user
fizzy card assign 579 --user USER_ID

# Mark as golden (important)
Expand Down
Loading