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
30 changes: 30 additions & 0 deletions SURFACE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ CMD fizzy board create
CMD fizzy board delete
CMD fizzy board help
CMD fizzy board list
CMD fizzy board publish
CMD fizzy board show
CMD fizzy board unpublish
CMD fizzy board update
CMD fizzy card
CMD fizzy card assign
Expand Down Expand Up @@ -296,6 +298,19 @@ FLAG fizzy board list --quiet type=bool
FLAG fizzy board list --styled type=bool
FLAG fizzy board list --token type=string
FLAG fizzy board list --verbose type=bool
FLAG fizzy board publish --agent type=bool
FLAG fizzy board publish --api-url type=string
FLAG fizzy board publish --count type=bool
FLAG fizzy board publish --help type=bool
FLAG fizzy board publish --ids-only type=bool
FLAG fizzy board publish --json type=bool
FLAG fizzy board publish --limit type=int
FLAG fizzy board publish --markdown type=bool
FLAG fizzy board publish --profile type=string
FLAG fizzy board publish --quiet type=bool
FLAG fizzy board publish --styled type=bool
FLAG fizzy board publish --token type=string
FLAG fizzy board publish --verbose type=bool
FLAG fizzy board show --agent type=bool
FLAG fizzy board show --api-url type=string
FLAG fizzy board show --count type=bool
Expand All @@ -309,6 +324,19 @@ FLAG fizzy board show --quiet type=bool
FLAG fizzy board show --styled type=bool
FLAG fizzy board show --token type=string
FLAG fizzy board show --verbose type=bool
FLAG fizzy board unpublish --agent type=bool
FLAG fizzy board unpublish --api-url type=string
FLAG fizzy board unpublish --count type=bool
FLAG fizzy board unpublish --help type=bool
FLAG fizzy board unpublish --ids-only type=bool
FLAG fizzy board unpublish --json type=bool
FLAG fizzy board unpublish --limit type=int
FLAG fizzy board unpublish --markdown type=bool
FLAG fizzy board unpublish --profile type=string
FLAG fizzy board unpublish --quiet type=bool
FLAG fizzy board unpublish --styled type=bool
FLAG fizzy board unpublish --token type=string
FLAG fizzy board unpublish --verbose type=bool
FLAG fizzy board update --agent type=bool
FLAG fizzy board update --all_access type=string
FLAG fizzy board update --api-url type=string
Expand Down Expand Up @@ -1853,7 +1881,9 @@ SUB fizzy board create
SUB fizzy board delete
SUB fizzy board help
SUB fizzy board list
SUB fizzy board publish
SUB fizzy board show
SUB fizzy board unpublish
SUB fizzy board update
SUB fizzy card
SUB fizzy card assign
Expand Down
77 changes: 77 additions & 0 deletions e2e/tests/board_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,83 @@ func TestBoardCRUD(t *testing.T) {
if id != boardID {
t.Errorf("expected id %q, got %q", boardID, id)
}

if publicURL := result.GetDataString("public_url"); publicURL != "" {
t.Errorf("expected unpublished board to omit public_url, got %q", publicURL)
}
})

t.Run("publish and unpublish board", func(t *testing.T) {
if boardID == "" {
t.Skip("no board ID from create test")
}

published := false
publishResult := h.Run("board", "publish", boardID)

// Only unpublish on exit if publish succeeded
t.Cleanup(func() {
if published {
h.Run("board", "unpublish", boardID)
}
})

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

if publishResult.Response == nil {
t.Fatal("expected JSON response from publish")
}

if !publishResult.Response.OK {
t.Fatalf("expected ok=true, error: %+v", publishResult.Response.Error)
}

published = true

publicURL := publishResult.GetDataString("public_url")
if publicURL == "" {
t.Fatal("expected public_url in publish response")
}

showPublished := h.Run("board", "show", boardID)
if showPublished.ExitCode != harness.ExitSuccess {
t.Fatalf("failed to show published board: %s", showPublished.Stderr)
}
if got := showPublished.GetDataString("public_url"); got != publicURL {
t.Errorf("expected public_url %q after publish, got %q", publicURL, got)
}

// Verify unpublish works (cleanup is skipped since we unpublish here)
unpublishResult := h.Run("board", "unpublish", boardID)
if unpublishResult.ExitCode != harness.ExitSuccess {
t.Fatalf("expected exit code %d, got %d\nstderr: %s\nstdout: %s",
harness.ExitSuccess, unpublishResult.ExitCode, unpublishResult.Stderr, unpublishResult.Stdout)
}

if unpublishResult.Response == nil {
t.Fatal("expected JSON response from unpublish")
}

if !unpublishResult.Response.OK {
t.Fatalf("expected ok=true, error: %+v", unpublishResult.Response.Error)
}

published = false

if !unpublishResult.GetDataBool("unpublished") {
t.Error("expected unpublished=true")
}

showUnpublished := h.Run("board", "show", boardID)
if showUnpublished.ExitCode != harness.ExitSuccess {
t.Fatalf("failed to show unpublished board: %s", showUnpublished.Stderr)
}
if got := showUnpublished.GetDataString("public_url"); got != "" {
t.Errorf("expected public_url to be removed after unpublish, got %q", got)
}
})

t.Run("update board name", func(t *testing.T) {
Expand Down
80 changes: 78 additions & 2 deletions internal/commands/board.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,12 @@ var boardShowCmd = &cobra.Command{

boardID := args[0]

data, _, err := getSDK().Boards().Get(cmd.Context(), boardID)
resp, err := getSDK().Get(cmd.Context(), "/boards/"+boardID+".json")
if err != nil {
return convertSDKError(err)
}

items := normalizeAny(data)
items := normalizeAny(resp.Data)

summary := "Board"
if board, ok := items.(map[string]any); ok {
Expand All @@ -115,6 +115,13 @@ var boardShowCmd = &cobra.Command{
breadcrumb("columns", fmt.Sprintf("fizzy column list --board %s", boardID), "List columns"),
breadcrumb("create-card", fmt.Sprintf("fizzy card create --board %s --title \"title\"", boardID), "Create card"),
}
if board, ok := items.(map[string]any); ok {
if publicURL, ok := board["public_url"].(string); ok && publicURL != "" {
breadcrumbs = append(breadcrumbs, breadcrumb("unpublish", fmt.Sprintf("fizzy board unpublish %s", boardID), "Disable public board link"))
} else {
breadcrumbs = append(breadcrumbs, breadcrumb("publish", fmt.Sprintf("fizzy board publish %s", boardID), "Create public board link"))
}
}

printDetail(items, summary, breadcrumbs)
return nil
Expand Down Expand Up @@ -272,6 +279,71 @@ var boardDeleteCmd = &cobra.Command{
},
}

var boardPublishCmd = &cobra.Command{
Use: "publish BOARD_ID",
Short: "Publish a board",
Long: "Publishes a board and returns its public share URL.",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
if err := requireAuthAndAccount(); err != nil {
return err
}

boardID := args[0]

client := getClient()
resp, err := client.Post("/boards/"+boardID+"/publication.json", nil)
if err != nil {
return err
}

breadcrumbs := []Breadcrumb{
breadcrumb("show", fmt.Sprintf("fizzy board show %s", boardID), "View board"),
breadcrumb("cards", fmt.Sprintf("fizzy card list --board %s", boardID), "List cards"),
breadcrumb("unpublish", fmt.Sprintf("fizzy board unpublish %s", boardID), "Disable public board link"),
}

data := resp.Data
if data == nil {
data = map[string]any{"published": true}
}

printMutation(data, "", breadcrumbs)
return nil
},
}

var boardUnpublishCmd = &cobra.Command{
Use: "unpublish BOARD_ID",
Short: "Unpublish a board",
Long: "Removes a board's public share URL.",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
if err := requireAuthAndAccount(); err != nil {
return err
}

boardID := args[0]

client := getClient()
_, err := client.Delete("/boards/" + boardID + "/publication.json")
if err != nil {
return err
}

breadcrumbs := []Breadcrumb{
breadcrumb("show", fmt.Sprintf("fizzy board show %s", boardID), "View board"),
breadcrumb("cards", fmt.Sprintf("fizzy card list --board %s", boardID), "List cards"),
breadcrumb("publish", fmt.Sprintf("fizzy board publish %s", boardID), "Create public board link"),
}

printMutation(map[string]any{
"unpublished": true,
}, "", breadcrumbs)
return nil
},
}

func init() {
rootCmd.AddCommand(boardCmd)

Expand All @@ -297,4 +369,8 @@ func init() {

// Delete
boardCmd.AddCommand(boardDeleteCmd)

// Publication
boardCmd.AddCommand(boardPublishCmd)
boardCmd.AddCommand(boardUnpublishCmd)
}
Loading
Loading