diff --git a/README.md b/README.md index 8b26c40..2a7a64a 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,26 @@ fizzy search "authentication" # Search across cards fizzy comment create --card 42 --body "Looks good!" # Add comment ``` +### Attachments + +Simple mode uses repeatable `--attach` and appends inline attachments to the end of card descriptions or comment bodies: + +```bash +fizzy card create --board ID --title "Bug report" --description "See attached" --attach screenshot.png +fizzy comment create --card 42 --attach logs.txt +fizzy comment create --card 42 --body_file comment.md --attach screenshot.png --attach trace.txt +``` + +Advanced mode still works when exact placement matters: + +```bash +SGID=$(fizzy upload file screenshot.png --jq '.data.attachable_sgid') +fizzy card create --board ID --title "Bug report" \ + --description "
See screenshot
Description
', got '%v'", body["description"]) } }) + + t.Run("uploads and appends single inline attachment", func(t *testing.T) { + tempDir := t.TempDir() + attachPath := writeTestAttachmentFile(t, tempDir, "single.txt", "single") + + mock := NewMockClient() + mock.PostResponse = &client.APIResponse{ + StatusCode: 201, + Data: map[string]any{"id": "abc", "number": 42}, + } + mock.UploadFileResponse = &client.APIResponse{ + StatusCode: 200, + Data: map[string]any{"attachable_sgid": "sgid-single"}, + } + + SetTestModeWithSDK(mock) + SetTestConfig("token", "account", "https://api.example.com") + defer resetTest() + + cardCreateBoard = "123" + cardCreateTitle = "Test" + cardCreateDescription = "See attached" + cardCreateAttach = []string{attachPath} + err := cardCreateCmd.RunE(cardCreateCmd, []string{}) + cardCreateBoard = "" + cardCreateTitle = "" + cardCreateDescription = "" + cardCreateAttach = nil + + assertExitCode(t, err, 0) + + if len(mock.UploadFileCalls) != 1 || mock.UploadFileCalls[0] != attachPath { + t.Fatalf("unexpected upload calls: %#v", mock.UploadFileCalls) + } + + body := mock.PostCalls[0].Body.(map[string]any) + expected := strings.Join([]string{ + "See attached", + `Existing description
", + }, + } + mock.PatchResponse = &client.APIResponse{StatusCode: 200, Data: map[string]any{"id": "abc"}} + mock.UploadFileResponse = &client.APIResponse{StatusCode: 200, Data: map[string]any{"attachable_sgid": "sgid-update"}} + + SetTestModeWithSDK(mock) + SetTestConfig("token", "account", "https://api.example.com") + defer resetTest() + + cardUpdateAttach = []string{attachPath} + err := cardUpdateCmd.RunE(cardUpdateCmd, []string{"42"}) + cardUpdateAttach = nil + + assertExitCode(t, err, 0) + if len(mock.GetCalls) == 0 || mock.GetCalls[0].Path != "/cards/42" { + t.Fatalf("expected existing card fetch before update, got %#v", mock.GetCalls) + } + body := mock.PatchCalls[0].Body.(map[string]any) + expected := strings.Join([]string{ + "Existing description
", + `Existing comment
", + "plain_text": "Existing comment", + }, + }, + } + mock.PatchResponse = &client.APIResponse{StatusCode: 200, Data: map[string]any{"id": "comment-1"}} + mock.UploadFileResponse = &client.APIResponse{StatusCode: 200, Data: map[string]any{"attachable_sgid": "sgid-update"}} + + SetTestModeWithSDK(mock) + SetTestConfig("token", "account", "https://api.example.com") + defer resetTest() + + commentUpdateCard = "42" + commentUpdateAttach = []string{attachPath} + err := commentUpdateCmd.RunE(commentUpdateCmd, []string{"comment-1"}) + commentUpdateCard = "" + commentUpdateAttach = nil + + assertExitCode(t, err, 0) + if len(mock.GetCalls) == 0 || mock.GetCalls[0].Path != "/cards/42/comments/comment-1" { + t.Fatalf("expected existing comment fetch before update, got %#v", mock.GetCalls) + } + body := mock.PatchCalls[0].Body.(map[string]any) + expected := strings.Join([]string{ + "Existing comment
", + `` tags for paragraphs, ` Commit $(git rev-parse --short HEAD):
fizzy card close 42
```
-### Create Card with Inline Image
+### Create Card with Inline Attachment
+Simple mode:
+```bash
+fizzy card create --board BOARD_ID --title "Bug Report" --description "See the screenshot below" --attach screenshot.png
+```
+
+Advanced/manual placement mode:
```bash
# Upload image
SGID=$(fizzy upload file screenshot.png --jq '.data.attachable_sgid')
@@ -1060,7 +1070,9 @@ Complete field reference for all resources. Use these exact field paths in jq qu
## Rich Text Formatting
-Card descriptions and comments support HTML. For multiple paragraphs with spacing:
+Card descriptions and comments support markdown or HTML. For simple inline attachments appended at the end, use `--attach PATH`.
+
+For exact placement, upload first and embed ` First paragraph.