diff --git a/.github/actions/setup-go/action.yml b/.github/actions/setup-go/action.yml new file mode 100644 index 0000000..6c4c259 --- /dev/null +++ b/.github/actions/setup-go/action.yml @@ -0,0 +1,29 @@ +name: Setup Go +description: 'Sets up Go environment with private modules' +inputs: + stainless-api-key: + required: false + description: the value of the STAINLESS_API_KEY secret +runs: + using: composite + steps: + - uses: stainless-api/retrieve-github-access-token@v1 + if: github.repository == 'stainless-sdks/agentmail-cli' + id: get_token + with: + repo: stainless-sdks/agentmail-go + stainless-api-key: ${{ inputs.stainless-api-key }} + + - name: Configure Git for access to the Go SDK's staging repo + if: github.repository == 'stainless-sdks/agentmail-cli' + shell: bash + run: git config --global url."https://x-access-token:${{ steps.get_token.outputs.github_access_token }}@github.com/stainless-sdks/agentmail-go".insteadOf "https://github.com/stainless-sdks/agentmail-go" + + - name: Setup go + uses: actions/setup-go@v5 + with: + go-version-file: ./go.mod + + - name: Bootstrap + shell: bash + run: ./scripts/bootstrap diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bb21721..1bb6cb6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,17 +1,22 @@ name: CI on: push: - branches-ignore: - - 'generated' - - 'codegen/**' - - 'integrated/**' - - 'stl-preview-head/**' - - 'stl-preview-base/**' + branches: + - '**' + - '!integrated/**' + - '!stl-preview-head/**' + - '!stl-preview-base/**' + - '!generated' + - '!codegen/**' + - 'codegen/stl/**' pull_request: branches-ignore: - 'stl-preview-head/**' - 'stl-preview-base/**' +env: + GOPRIVATE: github.com/agentmail-to/agentmail-go,github.com/stainless-sdks/agentmail-go + jobs: lint: timeout-minutes: 10 @@ -22,10 +27,14 @@ jobs: steps: - uses: actions/checkout@v6 - - name: Setup go - uses: actions/setup-go@v5 + - uses: ./.github/actions/setup-go with: - go-version-file: ./go.mod + stainless-api-key: ${{ secrets.STAINLESS_API_KEY }} + + - name: Link staging branch + if: github.repository == 'stainless-sdks/agentmail-cli' + run: | + ./scripts/link 'github.com/stainless-sdks/agentmail-go@${{ github.ref_name }}' || true - name: Bootstrap run: ./scripts/bootstrap @@ -44,10 +53,14 @@ jobs: steps: - uses: actions/checkout@v6 - - name: Setup go - uses: actions/setup-go@v5 + - uses: ./.github/actions/setup-go with: - go-version-file: ./go.mod + stainless-api-key: ${{ secrets.STAINLESS_API_KEY }} + + - name: Link staging branch + if: github.repository == 'stainless-sdks/agentmail-cli' + run: | + ./scripts/link 'github.com/stainless-sdks/agentmail-go@${{ github.ref_name }}' || true - name: Bootstrap run: ./scripts/bootstrap @@ -61,14 +74,18 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Get GitHub OIDC Token - if: github.repository == 'stainless-sdks/agentmail-cli' + if: |- + github.repository == 'stainless-sdks/agentmail-cli' && + !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc uses: actions/github-script@v8 with: script: core.setOutput('github_token', await core.getIDToken()); - name: Upload tarball - if: github.repository == 'stainless-sdks/agentmail-cli' + if: |- + github.repository == 'stainless-sdks/agentmail-cli' && + !startsWith(github.ref, 'refs/heads/stl/') env: URL: https://pkg.stainless.com/s AUTH: ${{ steps.github-oidc.outputs.github_token }} @@ -83,10 +100,14 @@ jobs: steps: - uses: actions/checkout@v6 - - name: Setup go - uses: actions/setup-go@v5 + - uses: ./.github/actions/setup-go with: - go-version-file: ./go.mod + stainless-api-key: ${{ secrets.STAINLESS_API_KEY }} + + - name: Link staging branch + if: github.repository == 'stainless-sdks/agentmail-cli' + run: | + ./scripts/link 'github.com/stainless-sdks/agentmail-go@${{ github.ref_name }}' || true - name: Bootstrap run: ./scripts/bootstrap diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 1bc5713..7412044 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.7.1" + ".": "0.7.2" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 85aa513..cb86e9f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 62 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/agentmail%2Fagentmail-161e9f5d786cbd431b293059ed3202a30936b4ec47aa100dd2344b6cc4b77ec0.yml -openapi_spec_hash: b4e026c4a83dab7c8766a9179377674d +configured_endpoints: 61 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/agentmail%2Fagentmail-7fdcd6b4651f31badd1999d492b21d2c53bc6f3a5f57ca0f6c354136b389bf1c.yml +openapi_spec_hash: bdd107c27a5e1e30b43bff0ae7195a10 config_hash: 2595ffb55fb009abe18a6566962fbf0a diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cac5a0..5724559 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,38 @@ # Changelog +## 0.7.2 (2026-03-19) + +Full Changelog: [v0.7.1...v0.7.2](https://github.com/agentmail-to/agentmail-cli/compare/v0.7.1...v0.7.2) + +### Features + +* add `--max-items` flag for paginated/streaming endpoints ([cab651f](https://github.com/agentmail-to/agentmail-cli/commit/cab651f16b51cc0b8fd8197307bd9a2a3149097f)) +* **api:** api update ([93ec607](https://github.com/agentmail-to/agentmail-cli/commit/93ec607579dc3c74a00c1559876f19159f17bf18)) +* **api:** api update ([922d06b](https://github.com/agentmail-to/agentmail-cli/commit/922d06ba6370e908121be1ce2a3dcb60a025a919)) +* **api:** api update ([5978d7a](https://github.com/agentmail-to/agentmail-cli/commit/5978d7ab85c90ec624165671208606c5d3bb9825)) +* **api:** api update ([212d624](https://github.com/agentmail-to/agentmail-cli/commit/212d6248a314de915377c0fa35c346e7b9fe3549)) +* **api:** api update ([b3aa3b4](https://github.com/agentmail-to/agentmail-cli/commit/b3aa3b49b6b1077ba92aa4146f7860dff0b05920)) +* support passing required body params through pipes ([5caad8a](https://github.com/agentmail-to/agentmail-cli/commit/5caad8a5272b56a28394d040333c420a9f853b56)) + + +### Bug Fixes + +* avoid reading from stdin unless request body is form encoded or json ([32f2697](https://github.com/agentmail-to/agentmail-cli/commit/32f26970e29bc6c1b02d2e543bda76b38d018d5a)) +* better support passing client args in any position ([632158a](https://github.com/agentmail-to/agentmail-cli/commit/632158a4431957bc86e8f0bc1b33adefb7067e59)) +* fix for encoding arrays with `any` type items ([7898e52](https://github.com/agentmail-to/agentmail-cli/commit/7898e52f357d2232cb5db0c22791692dabc13d30)) +* fix for test cases with newlines in YAML and better error reporting ([d0fbf69](https://github.com/agentmail-to/agentmail-cli/commit/d0fbf69778cfba589c91162a01bc111c19d03054)) +* improve linking behavior when developing on a branch not in the Go SDK ([7a56630](https://github.com/agentmail-to/agentmail-cli/commit/7a566301e20873025326c753da2fe601e455879b)) +* improved workflow for developing on branches ([eb3e18e](https://github.com/agentmail-to/agentmail-cli/commit/eb3e18ec65da5b7b9e43ba20993af7943807be89)) +* no longer require an API key when building on production repos ([d82fd7d](https://github.com/agentmail-to/agentmail-cli/commit/d82fd7d528fa133a93bf7d94165382d37fe873df)) +* only set client options when the corresponding CLI flag or env var is explicitly set ([6cfe6d4](https://github.com/agentmail-to/agentmail-cli/commit/6cfe6d4f1d49f539dde18233414d3c6132ec5dc9)) + + +### Chores + +* **ci:** skip uploading artifacts on stainless-internal branches ([5a4be3e](https://github.com/agentmail-to/agentmail-cli/commit/5a4be3e1c740c2b1f89d116f6cd9348fd81a5dae)) +* **internal:** codegen related update ([41d32f3](https://github.com/agentmail-to/agentmail-cli/commit/41d32f3b7bcb7c421d033e0d18c4cf70f7343dd2)) +* **internal:** tweak CI branches ([6d81988](https://github.com/agentmail-to/agentmail-cli/commit/6d8198801ce6a24c892d313650ef37cc7e3920b1)) + ## 0.7.1 (2026-03-06) Full Changelog: [v0.7.0...v0.7.1](https://github.com/agentmail-to/agentmail-cli/compare/v0.7.0...v0.7.1) diff --git a/internal/apiform/encoder.go b/internal/apiform/encoder.go index 16ca44b..857fe14 100644 --- a/internal/apiform/encoder.go +++ b/internal/apiform/encoder.go @@ -101,6 +101,15 @@ func (e *encoder) encodeArray(key string, val reflect.Value, writer *multipart.W var values []string for i := 0; i < val.Len(); i++ { item := val.Index(i) + if (item.Kind() == reflect.Pointer || item.Kind() == reflect.Interface) && item.IsNil() { + // Null values are sent as an empty string + values = append(values, "") + continue + } + // If item is an interface, reduce it to the concrete type + if item.Kind() == reflect.Interface { + item = item.Elem() + } var strValue string switch item.Kind() { case reflect.String: diff --git a/internal/binaryparam/binary_param.go b/internal/binaryparam/binary_param.go index 79357a3..40d4ecf 100644 --- a/internal/binaryparam/binary_param.go +++ b/internal/binaryparam/binary_param.go @@ -17,7 +17,7 @@ func FileOrStdin(stdin io.ReadCloser, path string) (io.ReadCloser, bool, error) // When the special glyph "-" is used, read from stdin. Although probably less necessary, also support // special Unix files that refer to stdin. switch path { - case stdinGlyph, "/dev/fd/0", "/dev/stdin": + case "", stdinGlyph, "/dev/fd/0", "/dev/stdin": return stdin, true, nil } diff --git a/internal/binaryparam/binary_param_test.go b/internal/binaryparam/binary_param_test.go index bdac3e9..7a66682 100644 --- a/internal/binaryparam/binary_param_test.go +++ b/internal/binaryparam/binary_param_test.go @@ -28,57 +28,32 @@ func TestFileOrStdin(t *testing.T) { require.False(t, stdinInUse) }) - t.Run("WithStdinGlyph", func(t *testing.T) { - tempFile := t.TempDir() + "/test_file.txt" - require.NoError(t, os.WriteFile(tempFile, []byte(expectedContents), 0600)) - - stubStdin, err := os.Open(tempFile) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, stubStdin.Close()) }) - - readCloser, stdinInUse, err := FileOrStdin(stubStdin, "-") - require.NoError(t, err) - - actualContents, err := io.ReadAll(readCloser) - require.NoError(t, err) - require.Equal(t, expectedContents, string(actualContents)) - - require.True(t, stdinInUse) - }) - - t.Run("WithDevFD0File", func(t *testing.T) { - tempFile := t.TempDir() + "/dev_fd_0" - require.NoError(t, os.WriteFile(tempFile, []byte(expectedContents), 0600)) - - stubStdin, err := os.Open(tempFile) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, stubStdin.Close()) }) - - readCloser, stdinInUse, err := FileOrStdin(stubStdin, "/dev/fd/0") - require.NoError(t, err) - - actualContents, err := io.ReadAll(readCloser) - require.NoError(t, err) - require.Equal(t, expectedContents, string(actualContents)) - - require.True(t, stdinInUse) - }) - - t.Run("WithDevStdinFile", func(t *testing.T) { - tempFile := t.TempDir() + "/dev_stdin" - require.NoError(t, os.WriteFile(tempFile, []byte(expectedContents), 0600)) - - stubStdin, err := os.Open(tempFile) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, stubStdin.Close()) }) - - readCloser, stdinInUse, err := FileOrStdin(stubStdin, "/dev/stdin") - require.NoError(t, err) - - actualContents, err := io.ReadAll(readCloser) - require.NoError(t, err) - require.Equal(t, expectedContents, string(actualContents)) - - require.True(t, stdinInUse) - }) + stdinTests := []struct { + testName string + path string + }{ + {"TestEmptyString", ""}, + {"TestDash", "-"}, + {"TestDevStdin", "/dev/stdin"}, + {"TestDevFD0", "/dev/fd/0"}, + } + for _, test := range stdinTests { + t.Run(test.testName, func(t *testing.T) { + tempFile := t.TempDir() + "/test_file.txt" + require.NoError(t, os.WriteFile(tempFile, []byte(expectedContents), 0600)) + + stubStdin, err := os.Open(tempFile) + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, stubStdin.Close()) }) + + readCloser, stdinInUse, err := FileOrStdin(stubStdin, test.path) + require.NoError(t, err) + + actualContents, err := io.ReadAll(readCloser) + require.NoError(t, err) + require.Equal(t, expectedContents, string(actualContents)) + + require.True(t, stdinInUse) + }) + } } diff --git a/internal/mocktest/mocktest.go b/internal/mocktest/mocktest.go index 870ca73..e1c483e 100644 --- a/internal/mocktest/mocktest.go +++ b/internal/mocktest/mocktest.go @@ -1,6 +1,7 @@ package mocktest import ( + "bytes" "context" "fmt" "net" @@ -14,6 +15,7 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -54,8 +56,14 @@ func restoreNetwork(origClient, origDefault http.RoundTripper) { } // TestRunMockTestWithFlags runs a test against a mock server with the provided -// CLI flags and ensures it succeeds -func TestRunMockTestWithFlags(t *testing.T, flags ...string) { +// CLI args and ensures it succeeds +func TestRunMockTestWithFlags(t *testing.T, args ...string) { + TestRunMockTestWithPipeAndFlags(t, nil, args...) +} + +// TestRunMockTestWithPipeAndFlags runs a test against a mock server with the provided +// data piped over stdin and CLI args and ensures it succeeds +func TestRunMockTestWithPipeAndFlags(t *testing.T, pipeData []byte, args ...string) { origClient, origDefault := blockNetworkExceptMockServer() defer restoreNetwork(origClient, origDefault) @@ -71,52 +79,18 @@ func TestRunMockTestWithFlags(t *testing.T, flags ...string) { _, filename, _, ok := runtime.Caller(0) require.True(t, ok, "Could not get current file path") dirPath := filepath.Dir(filename) - project := filepath.Join(dirPath, "..", "..", "cmd", "...") - - args := []string{"run", project, "--base-url", mockServerURL.String()} - args = append(args, flags...) - - t.Logf("Testing command: agentmail %s", strings.Join(args[4:], " ")) - - cliCmd := exec.Command("go", args...) - - // Pipe the CLI tool's output into `head` so it doesn't hang when simulating - // paginated or streamed endpoints. 100 lines of output should be enough to - // test that the API endpoint worked, or report back a meaningful amount of - // data if something went wrong. - headCmd := exec.Command("head", "-n", "100") - pipe, err := cliCmd.StdoutPipe() - require.NoError(t, err, "Failed to create pipe for CLI command") - headCmd.Stdin = pipe - - // Capture `head` output and CLI command stderr outputs: - var output strings.Builder - headCmd.Stdout = &output - headCmd.Stderr = &output - cliCmd.Stderr = &output - - // First start `head`, so it's ready for data to come in: - err = headCmd.Start() - require.NoError(t, err, "Failed to start `head` command") - - // Next start the CLI command so it can pipe data to `head` without - // buffering any data in advance: - err = cliCmd.Start() - require.NoError(t, err, "Failed to start CLI command") - - // Ensure that the stdout pipe is closed as soon as `head` exits, to let the - // CLI tool know that no more output is needed and it can stop streaming - // test data for streaming/paginated endpoints. This needs to happen before - // calling `cliCmd.Wait()`, otherwise there will be a deadlock. - err = headCmd.Wait() - pipe.Close() - require.NoError(t, err, "`head` command finished with an error") - - // Finally, wait for the CLI tool to finish up: - err = cliCmd.Wait() - require.NoError(t, err, "CLI command failed\n%s", output.String()) - - t.Logf("Test passed successfully\nOutput:\n%s", output.String()) + project := filepath.Join(dirPath, "..", "..", "cmd", "agentmail") + + args = append([]string{"run", project, "--base-url", mockServerURL.String()}, args...) + + t.Logf("Testing command: go run ./cmd/agentmail %s", strings.Join(args[2:], " ")) + + cmd := exec.Command("go", args...) + cmd.Stdin = bytes.NewReader(pipeData) + output, err := cmd.CombinedOutput() + assert.NoError(t, err, "Test failed\nError: %v\nOutput: %s", err, output) + + t.Logf("Test passed successfully\nOutput:\n%s", string(output)) } func TestFile(t *testing.T, contents string) string { diff --git a/internal/requestflag/requestflag.go b/internal/requestflag/requestflag.go index cb11412..21a8a69 100644 --- a/internal/requestflag/requestflag.go +++ b/internal/requestflag/requestflag.go @@ -110,6 +110,40 @@ func ExtractRequestContents(cmd *cli.Command) RequestContents { return res } +func GetMissingRequiredFlags(cmd *cli.Command, body any) []cli.Flag { + missing := []cli.Flag{} + for _, flag := range cmd.Flags { + if flag.IsSet() { + continue + } + + if required, ok := flag.(cli.RequiredFlag); ok && required.IsRequired() { + missing = append(missing, flag) + continue + } + + if r, ok := flag.(RequiredFlagOrStdin); !ok || !r.IsRequiredAsFlagOrStdin() { + continue + } + + if toSend, ok := flag.(InRequest); ok { + if toSend.IsBodyRoot() { + if body != nil { + continue + } + } else if bodyPath := toSend.GetBodyPath(); bodyPath != "" { + if bodyMap, ok := body.(map[string]any); ok { + if _, found := bodyMap[bodyPath]; found { + continue + } + } + } + } + missing = append(missing, flag) + } + return missing +} + // Implementation of the cli.Flag interface var _ cli.Flag = (*Flag[any])(nil) // Type assertion to ensure interface compliance @@ -221,6 +255,19 @@ func (f *Flag[T]) SetCategory(c string) { var _ cli.RequiredFlag = (*Flag[any])(nil) // Type assertion to ensure interface compliance func (f *Flag[T]) IsRequired() bool { + // Intentionally don't use `f.Required`, because request flags may be passed + // over stdin as well as by flag. + if f.BodyPath != "" || f.BodyRoot { + return false + } + return f.Required +} + +type RequiredFlagOrStdin interface { + IsRequiredAsFlagOrStdin() bool +} + +func (f *Flag[T]) IsRequiredAsFlagOrStdin() bool { return f.Required } @@ -327,6 +374,14 @@ func (f *Flag[T]) Count() int { return f.count } +// Implementation for the cli.LocalFlag interface +var _ cli.LocalFlag = (*Flag[any])(nil) // Type assertion to ensure interface compliance + +func (f Flag[T]) IsLocal() bool { + // By default, all request flags are local, i.e. can be provided at any part of the CLI command. + return true +} + // cliValue is a generic implementation of cli.Value for common types type cliValue[ T []any | []map[string]any | []DateTimeValue | []DateValue | []TimeValue | []string | []float64 | diff --git a/pkg/cmd/apikey.go b/pkg/cmd/apikey.go index adfef33..b29cebc 100644 --- a/pkg/cmd/apikey.go +++ b/pkg/cmd/apikey.go @@ -56,21 +56,6 @@ var apiKeysList = cli.Command{ HideHelpCommand: true, } -var apiKeysDelete = cli.Command{ - Name: "delete", - Usage: "Delete API Key", - Suggest: true, - Flags: []cli.Flag{ - &requestflag.Flag[string]{ - Name: "api-key", - Usage: "ID of api key.", - Required: true, - }, - }, - Action: handleAPIKeysDelete, - HideHelpCommand: true, -} - func handleAPIKeysCreate(ctx context.Context, cmd *cli.Command) error { client := agentmail.NewClient(getDefaultRequestOptions(cmd)...) unusedArgs := cmd.Args().Slice() @@ -138,28 +123,3 @@ func handleAPIKeysList(ctx context.Context, cmd *cli.Command) error { transform := cmd.Root().String("transform") return ShowJSON(os.Stdout, "api-keys list", obj, format, transform) } - -func handleAPIKeysDelete(ctx context.Context, cmd *cli.Command) error { - client := agentmail.NewClient(getDefaultRequestOptions(cmd)...) - unusedArgs := cmd.Args().Slice() - if !cmd.IsSet("api-key") && len(unusedArgs) > 0 { - cmd.Set("api-key", unusedArgs[0]) - unusedArgs = unusedArgs[1:] - } - if len(unusedArgs) > 0 { - return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs) - } - - options, err := flagOptions( - cmd, - apiquery.NestedQueryFormatBrackets, - apiquery.ArrayQueryFormatComma, - EmptyBody, - false, - ) - if err != nil { - return err - } - - return client.APIKeys.Delete(ctx, cmd.Value("api-key").(string), options...) -} diff --git a/pkg/cmd/apikey_test.go b/pkg/cmd/apikey_test.go index 303f9b0..30354c7 100644 --- a/pkg/cmd/apikey_test.go +++ b/pkg/cmd/apikey_test.go @@ -10,32 +10,36 @@ import ( func TestAPIKeysCreate(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "api-keys", "create", - "--api-key", "string", - "--name", "name", - ) -} + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "api-keys", "create", + "--name", "name", + ) + }) -func TestAPIKeysList(t *testing.T) { - t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "api-keys", "list", - "--api-key", "string", - "--ascending=true", - "--limit", "0", - "--page-token", "page_token", - ) + t.Run("piping data", func(t *testing.T) { + // Test piping YAML data over stdin + pipeData := []byte("name: name") + mocktest.TestRunMockTestWithPipeAndFlags( + t, pipeData, + "--api-key", "string", + "api-keys", "create", + ) + }) } -func TestAPIKeysDelete(t *testing.T) { +func TestAPIKeysList(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "api-keys", "delete", - "--api-key", "string", - "--api-key", "api_key", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "api-keys", "list", + "--ascending=true", + "--limit", "0", + "--page-token", "page_token", + ) + }) } diff --git a/pkg/cmd/cmd.go b/pkg/cmd/cmd.go index 05af211..edca0d6 100644 --- a/pkg/cmd/cmd.go +++ b/pkg/cmd/cmd.go @@ -203,7 +203,6 @@ func init() { Commands: []*cli.Command{ &apiKeysCreate, &apiKeysList, - &apiKeysDelete, }, }, { diff --git a/pkg/cmd/cmdutil.go b/pkg/cmd/cmdutil.go index 8b6cc8d..a803367 100644 --- a/pkg/cmd/cmdutil.go +++ b/pkg/cmd/cmdutil.go @@ -36,7 +36,9 @@ func getDefaultRequestOptions(cmd *cli.Command) []option.RequestOption { option.WithHeader("X-Stainless-Package-Version", Version), option.WithHeader("X-Stainless-Runtime", "cli"), option.WithHeader("X-Stainless-CLI-Command", cmd.FullName()), - option.WithAPIKey(cmd.String("api-key")), + } + if cmd.IsSet("api-key") { + opts = append(opts, option.WithAPIKey(cmd.String("api-key"))) } // Override base URL if the --base-url flag is provided @@ -362,7 +364,7 @@ type HasRawJSON interface { // For an iterator over different value types, display its values to the user in // different formats. -func ShowJSONIterator[T any](stdout *os.File, title string, iter jsonview.Iterator[T], format string, transform string) error { +func ShowJSONIterator[T any](stdout *os.File, title string, iter jsonview.Iterator[T], format string, transform string, itemsToDisplay int64) error { if format == "explore" { return jsonview.ExploreJSONStream(title, iter) } @@ -378,6 +380,9 @@ func ShowJSONIterator[T any](stdout *os.File, title string, iter jsonview.Iterat output := []byte{} numberOfNewlines := 0 for iter.Next() { + if itemsToDisplay == 0 { + break + } item := iter.Current() var obj gjson.Result if hasRaw, ok := any(item).(HasRawJSON); ok { @@ -395,6 +400,7 @@ func ShowJSONIterator[T any](stdout *os.File, title string, iter jsonview.Iterat } output = append(output, json...) + itemsToDisplay -= 1 numberOfNewlines += countTerminalLines(json, terminalWidth) // If the output won't fit in the terminal window, stream it to a pager @@ -421,6 +427,9 @@ func ShowJSONIterator[T any](stdout *os.File, title string, iter jsonview.Iterat } for iter.Next() { + if itemsToDisplay == 0 { + break + } item := iter.Current() var obj gjson.Result if hasRaw, ok := any(item).(HasRawJSON); ok { @@ -435,6 +444,7 @@ func ShowJSONIterator[T any](stdout *os.File, title string, iter jsonview.Iterat if err := ShowJSON(pager, title, obj, format, transform); err != nil { return err } + itemsToDisplay -= 1 } return iter.Err() }) diff --git a/pkg/cmd/domain.go b/pkg/cmd/domain.go index 4a5e8d6..3341305 100644 --- a/pkg/cmd/domain.go +++ b/pkg/cmd/domain.go @@ -22,7 +22,7 @@ var domainsCreate = cli.Command{ Flags: []cli.Flag{ &requestflag.Flag[string]{ Name: "domain", - Usage: `The name of the domain. (e.g., "example.com")`, + Usage: "The name of the domain (e.g., `example.com`).", Required: true, BodyPath: "domain", }, @@ -44,7 +44,7 @@ var domainsRetrieve = cli.Command{ Flags: []cli.Flag{ &requestflag.Flag[string]{ Name: "domain-id", - Usage: `The name of the domain. (e.g., " your-domain.com")`, + Usage: "The ID of the domain.", Required: true, }, }, @@ -84,7 +84,7 @@ var domainsDelete = cli.Command{ Flags: []cli.Flag{ &requestflag.Flag[string]{ Name: "domain-id", - Usage: `The name of the domain. (e.g., " your-domain.com")`, + Usage: "The ID of the domain.", Required: true, }, }, @@ -99,7 +99,7 @@ var domainsGetZoneFile = cli.Command{ Flags: []cli.Flag{ &requestflag.Flag[string]{ Name: "domain-id", - Usage: `The name of the domain. (e.g., " your-domain.com")`, + Usage: "The ID of the domain.", Required: true, }, }, @@ -114,7 +114,7 @@ var domainsVerify = cli.Command{ Flags: []cli.Flag{ &requestflag.Flag[string]{ Name: "domain-id", - Usage: `The name of the domain. (e.g., " your-domain.com")`, + Usage: "The ID of the domain.", Required: true, }, }, diff --git a/pkg/cmd/domain_test.go b/pkg/cmd/domain_test.go index b2a963d..4f055bb 100644 --- a/pkg/cmd/domain_test.go +++ b/pkg/cmd/domain_test.go @@ -10,63 +10,87 @@ import ( func TestDomainsCreate(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "domains", "create", - "--api-key", "string", - "--domain", "domain", - "--feedback-enabled=true", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "domains", "create", + "--domain", "domain", + "--feedback-enabled=true", + ) + }) + + t.Run("piping data", func(t *testing.T) { + // Test piping YAML data over stdin + pipeData := []byte("" + + "domain: domain\n" + + "feedback_enabled: true\n") + mocktest.TestRunMockTestWithPipeAndFlags( + t, pipeData, + "--api-key", "string", + "domains", "create", + ) + }) } func TestDomainsRetrieve(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "domains", "retrieve", - "--api-key", "string", - "--domain-id", "domain_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "domains", "retrieve", + "--domain-id", "domain_id", + ) + }) } func TestDomainsList(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "domains", "list", - "--api-key", "string", - "--ascending=true", - "--limit", "0", - "--page-token", "page_token", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "domains", "list", + "--ascending=true", + "--limit", "0", + "--page-token", "page_token", + ) + }) } func TestDomainsDelete(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "domains", "delete", - "--api-key", "string", - "--domain-id", "domain_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "domains", "delete", + "--domain-id", "domain_id", + ) + }) } func TestDomainsGetZoneFile(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "domains", "get-zone-file", - "--api-key", "string", - "--domain-id", "domain_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "domains", "get-zone-file", + "--domain-id", "domain_id", + ) + }) } func TestDomainsVerify(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "domains", "verify", - "--api-key", "string", - "--domain-id", "domain_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "domains", "verify", + "--domain-id", "domain_id", + ) + }) } diff --git a/pkg/cmd/draft_test.go b/pkg/cmd/draft_test.go index 67b327f..25c9dbd 100644 --- a/pkg/cmd/draft_test.go +++ b/pkg/cmd/draft_test.go @@ -10,25 +10,29 @@ import ( func TestDraftsRetrieve(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "drafts", "retrieve", - "--api-key", "string", - "--draft-id", "draft_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "drafts", "retrieve", + "--draft-id", "draft_id", + ) + }) } func TestDraftsList(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "drafts", "list", - "--api-key", "string", - "--after", "'2019-12-27T18:11:19.117Z'", - "--ascending=true", - "--before", "'2019-12-27T18:11:19.117Z'", - "--label", "[string]", - "--limit", "0", - "--page-token", "page_token", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "drafts", "list", + "--after", "'2019-12-27T18:11:19.117Z'", + "--ascending=true", + "--before", "'2019-12-27T18:11:19.117Z'", + "--label", "[string]", + "--limit", "0", + "--page-token", "page_token", + ) + }) } diff --git a/pkg/cmd/flagoptions.go b/pkg/cmd/flagoptions.go index 1dce3d4..d9976d3 100644 --- a/pkg/cmd/flagoptions.go +++ b/pkg/cmd/flagoptions.go @@ -41,6 +41,9 @@ const ( ) func embedFiles(obj any, embedStyle FileEmbedStyle) (any, error) { + if obj == nil { + return obj, nil + } v := reflect.ValueOf(obj) result, err := embedFilesValue(v, embedStyle) if err != nil { @@ -207,40 +210,54 @@ func flagOptions( // This parameter is true if stdin is already in use to pass a binary parameter by using the special value // "-". In this case, we won't attempt to read it as a JSON/YAML blob for options setting. - stdinInUse bool, + ignoreStdin bool, ) ([]option.RequestOption, error) { var options []option.RequestOption if cmd.Bool("debug") { options = append(options, option.WithMiddleware(debugmiddleware.NewRequestLogger().Middleware())) } - flagContents := requestflag.ExtractRequestContents(cmd) + requestContents := requestflag.ExtractRequestContents(cmd) - var bodyData any - var pipeData []byte - if isInputPiped() && !stdinInUse { - var err error - pipeData, err = io.ReadAll(os.Stdin) + if (bodyType == MultipartFormEncoded || bodyType == ApplicationJSON) && !ignoreStdin && isInputPiped() { + pipeData, err := io.ReadAll(os.Stdin) if err != nil { return nil, err } - } - if len(pipeData) > 0 { - if err := yaml.Unmarshal(pipeData, &bodyData); err == nil { + if len(pipeData) > 0 { + var bodyData any + if err := yaml.Unmarshal(pipeData, &bodyData); err != nil { + return nil, fmt.Errorf("Failed to parse piped data as YAML/JSON:\n%w", err) + } if bodyMap, ok := bodyData.(map[string]any); ok { - if flagMap, ok := flagContents.Body.(map[string]any); ok { + if flagMap, ok := requestContents.Body.(map[string]any); ok { maps.Copy(bodyMap, flagMap) + requestContents.Body = bodyMap } else { - bodyData = flagContents.Body + bodyData = requestContents.Body } - } else if flagMap, ok := flagContents.Body.(map[string]any); ok && len(flagMap) > 0 { + } else if flagMap, ok := requestContents.Body.(map[string]any); ok && len(flagMap) > 0 { return nil, fmt.Errorf("Cannot merge flags with a body that is not a map: %v", bodyData) + } else { + requestContents.Body = bodyData } } - } else { - // No piped input, just use body flag values as a map - bodyData = flagContents.Body + } + + if missingFlags := requestflag.GetMissingRequiredFlags(cmd, requestContents.Body); len(missingFlags) > 0 { + var buf bytes.Buffer + cli.HelpPrinter(&buf, cli.SubcommandHelpTemplate, cmd) + usage := buf.String() + if len(missingFlags) == 1 { + return nil, fmt.Errorf("%sRequired flag %q not set", usage, missingFlags[0].Names()[0]) + } else { + names := []string{} + for _, flag := range missingFlags { + names = append(names, flag.Names()[0]) + } + return nil, fmt.Errorf("%sRequired flags %q not set", usage, strings.Join(names, ", ")) + } } // Embed files passed as "@file.jpg" in the request body, headers, and query: @@ -248,19 +265,22 @@ func flagOptions( if bodyType == ApplicationOctetStream || bodyType == MultipartFormEncoded { embedStyle = EmbedIOReader } - bodyData, err := embedFiles(bodyData, embedStyle) - if err != nil { + + if embedded, err := embedFiles(requestContents.Body, embedStyle); err != nil { return nil, err + } else { + requestContents.Body = embedded } - if headersWithFiles, err := embedFiles(flagContents.Headers, EmbedText); err != nil { + + if headersWithFiles, err := embedFiles(requestContents.Headers, EmbedText); err != nil { return nil, err } else { - flagContents.Headers = headersWithFiles.(map[string]any) + requestContents.Headers = headersWithFiles.(map[string]any) } - if queriesWithFiles, err := embedFiles(flagContents.Queries, EmbedText); err != nil { + if queriesWithFiles, err := embedFiles(requestContents.Queries, EmbedText); err != nil { return nil, err } else { - flagContents.Queries = queriesWithFiles.(map[string]any) + requestContents.Queries = queriesWithFiles.(map[string]any) } querySettings := apiquery.QuerySettings{ @@ -269,7 +289,7 @@ func flagOptions( } // Add query parameters: - if values, err := apiquery.MarshalWithSettings(flagContents.Queries, querySettings); err != nil { + if values, err := apiquery.MarshalWithSettings(requestContents.Queries, querySettings); err != nil { return nil, err } else { for k, vs := range values { @@ -289,7 +309,7 @@ func flagOptions( NestedFormat: apiquery.NestedQueryFormatDots, ArrayFormat: apiquery.ArrayQueryFormatRepeat, } - if values, err := apiquery.MarshalWithSettings(flagContents.Headers, headerSettings); err != nil { + if values, err := apiquery.MarshalWithSettings(requestContents.Headers, headerSettings); err != nil { return nil, err } else { for k, vs := range values { @@ -312,9 +332,9 @@ func flagOptions( writer := multipart.NewWriter(buf) // For multipart/form-encoded, we need a map structure - bodyMap, ok := bodyData.(map[string]any) + bodyMap, ok := requestContents.Body.(map[string]any) if !ok { - return nil, fmt.Errorf("Cannot send a non-map value to a form-encoded endpoint: %v\n", bodyData) + return nil, fmt.Errorf("Cannot send a non-map value to a form-encoded endpoint: %v\n", requestContents.Body) } encodingFormat := apiform.FormatComma if err := apiform.MarshalWithSettings(bodyMap, writer, encodingFormat); err != nil { @@ -326,19 +346,25 @@ func flagOptions( options = append(options, option.WithRequestBody(writer.FormDataContentType(), buf)) case ApplicationJSON: - bodyBytes, err := json.Marshal(bodyData) + bodyBytes, err := json.Marshal(requestContents.Body) if err != nil { return nil, err } options = append(options, option.WithRequestBody("application/json", bodyBytes)) case ApplicationOctetStream: - if bodyBytes, ok := bodyData.([]byte); ok { + // If there is a body root parameter, that will handle setting the request body, we don't need to do it here. + for _, flag := range cmd.Flags { + if toSend, ok := flag.(requestflag.InRequest); ok && toSend.IsBodyRoot() { + return options, nil + } + } + if bodyBytes, ok := requestContents.Body.([]byte); ok { options = append(options, option.WithRequestBody("application/octet-stream", bodyBytes)) - } else if bodyStr, ok := bodyData.(string); ok { + } else if bodyStr, ok := requestContents.Body.(string); ok { options = append(options, option.WithRequestBody("application/octet-stream", []byte(bodyStr))) } else { - return nil, fmt.Errorf("Unsupported body for application/octet-stream: %v", bodyData) + return nil, fmt.Errorf("Unsupported body for application/octet-stream: %v", requestContents.Body) } default: diff --git a/pkg/cmd/inbox.go b/pkg/cmd/inbox.go index c091c67..40ac88d 100644 --- a/pkg/cmd/inbox.go +++ b/pkg/cmd/inbox.go @@ -123,7 +123,7 @@ var inboxesDelete = cli.Command{ var inboxesListMetrics = cli.Command{ Name: "list-metrics", - Usage: "List Metrics", + Usage: "Query Metrics", Suggest: true, Flags: []cli.Flag{ &requestflag.Flag[string]{ @@ -132,22 +132,35 @@ var inboxesListMetrics = cli.Command{ Required: true, }, &requestflag.Flag[any]{ - Name: "end-timestamp", - Usage: "End timestamp for the metrics query range.", - Required: true, - QueryPath: "end_timestamp", + Name: "descending", + Usage: "Sort in descending order.", + QueryPath: "descending", }, &requestflag.Flag[any]{ - Name: "start-timestamp", - Usage: "Start timestamp for the metrics query range.", - Required: true, - QueryPath: "start_timestamp", + Name: "end", + Usage: "End timestamp for the query.", + QueryPath: "end", }, &requestflag.Flag[any]{ Name: "event-type", - Usage: "List of metric event types to filter by.", + Usage: "List of metric event types to query.", QueryPath: "event_types", }, + &requestflag.Flag[any]{ + Name: "limit", + Usage: "Limit on number of buckets to return.", + QueryPath: "limit", + }, + &requestflag.Flag[any]{ + Name: "period", + Usage: "Period in number of seconds for the query.", + QueryPath: "period", + }, + &requestflag.Flag[any]{ + Name: "start", + Usage: "Start timestamp for the query.", + QueryPath: "start", + }, }, Action: handleInboxesListMetrics, HideHelpCommand: true, diff --git a/pkg/cmd/inbox_test.go b/pkg/cmd/inbox_test.go index 58e6af7..7d87b49 100644 --- a/pkg/cmd/inbox_test.go +++ b/pkg/cmd/inbox_test.go @@ -10,69 +10,109 @@ import ( func TestInboxesCreate(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes", "create", - "--api-key", "string", - "--client-id", "client_id", - "--display-name", "display_name", - "--domain", "domain", - "--username", "username", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes", "create", + "--client-id", "client_id", + "--display-name", "display_name", + "--domain", "domain", + "--username", "username", + ) + }) + + t.Run("piping data", func(t *testing.T) { + // Test piping YAML data over stdin + pipeData := []byte("" + + "client_id: client_id\n" + + "display_name: display_name\n" + + "domain: domain\n" + + "username: username\n") + mocktest.TestRunMockTestWithPipeAndFlags( + t, pipeData, + "--api-key", "string", + "inboxes", "create", + ) + }) } func TestInboxesRetrieve(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes", "retrieve", - "--api-key", "string", - "--inbox-id", "inbox_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes", "retrieve", + "--inbox-id", "inbox_id", + ) + }) } func TestInboxesUpdate(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes", "update", - "--api-key", "string", - "--inbox-id", "inbox_id", - "--display-name", "display_name", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes", "update", + "--inbox-id", "inbox_id", + "--display-name", "display_name", + ) + }) + + t.Run("piping data", func(t *testing.T) { + // Test piping YAML data over stdin + pipeData := []byte("display_name: display_name") + mocktest.TestRunMockTestWithPipeAndFlags( + t, pipeData, + "--api-key", "string", + "inboxes", "update", + "--inbox-id", "inbox_id", + ) + }) } func TestInboxesList(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes", "list", - "--api-key", "string", - "--ascending=true", - "--limit", "0", - "--page-token", "page_token", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes", "list", + "--ascending=true", + "--limit", "0", + "--page-token", "page_token", + ) + }) } func TestInboxesDelete(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes", "delete", - "--api-key", "string", - "--inbox-id", "inbox_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes", "delete", + "--inbox-id", "inbox_id", + ) + }) } func TestInboxesListMetrics(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes", "list-metrics", - "--api-key", "string", - "--inbox-id", "inbox_id", - "--end-timestamp", "'2019-12-27T18:11:19.117Z'", - "--start-timestamp", "'2019-12-27T18:11:19.117Z'", - "--event-type", "[message.sent]", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes", "list-metrics", + "--inbox-id", "inbox_id", + "--descending=true", + "--end", "'2019-12-27T18:11:19.117Z'", + "--event-type", "[message.sent]", + "--limit", "0", + "--period", "period", + "--start", "'2019-12-27T18:11:19.117Z'", + ) + }) } diff --git a/pkg/cmd/inboxdraft_test.go b/pkg/cmd/inboxdraft_test.go index f7c783a..c1ef2e5 100644 --- a/pkg/cmd/inboxdraft_test.go +++ b/pkg/cmd/inboxdraft_test.go @@ -11,119 +11,208 @@ import ( func TestInboxesDraftsCreate(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:drafts", "create", - "--api-key", "string", - "--inbox-id", "inbox_id", - "--attachment", "[{content: content, content_disposition: inline, content_id: content_id, content_type: content_type, filename: filename, url: url}]", - "--bcc", "[string]", - "--cc", "[string]", - "--client-id", "client_id", - "--html", "html", - "--in-reply-to", "in_reply_to", - "--label", "[string]", - "--reply-to", "[string]", - "--send-at", "'2019-12-27T18:11:19.117Z'", - "--subject", "subject", - "--text", "text", - "--to", "[string]", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:drafts", "create", + "--inbox-id", "inbox_id", + "--attachment", "[{content: content, content_disposition: inline, content_id: content_id, content_type: content_type, filename: filename, url: url}]", + "--bcc", "[string]", + "--cc", "[string]", + "--client-id", "client_id", + "--html", "html", + "--in-reply-to", "in_reply_to", + "--label", "[string]", + "--reply-to", "[string]", + "--send-at", "'2019-12-27T18:11:19.117Z'", + "--subject", "subject", + "--text", "text", + "--to", "[string]", + ) + }) - // Check that inner flags have been set up correctly - requestflag.CheckInnerFlags(inboxesDraftsCreate) + t.Run("inner flags", func(t *testing.T) { + // Check that inner flags have been set up correctly + requestflag.CheckInnerFlags(inboxesDraftsCreate) - // Alternative argument passing style using inner flags - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:drafts", "create", - "--inbox-id", "inbox_id", - "--attachment.content", "content", - "--attachment.content-disposition", "inline", - "--attachment.content-id", "content_id", - "--attachment.content-type", "content_type", - "--attachment.filename", "filename", - "--attachment.url", "url", - "--bcc", "[string]", - "--cc", "[string]", - "--client-id", "client_id", - "--html", "html", - "--in-reply-to", "in_reply_to", - "--label", "[string]", - "--reply-to", "[string]", - "--send-at", "'2019-12-27T18:11:19.117Z'", - "--subject", "subject", - "--text", "text", - "--to", "[string]", - ) + // Alternative argument passing style using inner flags + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:drafts", "create", + "--inbox-id", "inbox_id", + "--attachment.content", "content", + "--attachment.content-disposition", "inline", + "--attachment.content-id", "content_id", + "--attachment.content-type", "content_type", + "--attachment.filename", "filename", + "--attachment.url", "url", + "--bcc", "[string]", + "--cc", "[string]", + "--client-id", "client_id", + "--html", "html", + "--in-reply-to", "in_reply_to", + "--label", "[string]", + "--reply-to", "[string]", + "--send-at", "'2019-12-27T18:11:19.117Z'", + "--subject", "subject", + "--text", "text", + "--to", "[string]", + ) + }) + + t.Run("piping data", func(t *testing.T) { + // Test piping YAML data over stdin + pipeData := []byte("" + + "attachments:\n" + + " - content: content\n" + + " content_disposition: inline\n" + + " content_id: content_id\n" + + " content_type: content_type\n" + + " filename: filename\n" + + " url: url\n" + + "bcc:\n" + + " - string\n" + + "cc:\n" + + " - string\n" + + "client_id: client_id\n" + + "html: html\n" + + "in_reply_to: in_reply_to\n" + + "labels:\n" + + " - string\n" + + "reply_to:\n" + + " - string\n" + + "send_at: '2019-12-27T18:11:19.117Z'\n" + + "subject: subject\n" + + "text: text\n" + + "to:\n" + + " - string\n") + mocktest.TestRunMockTestWithPipeAndFlags( + t, pipeData, + "--api-key", "string", + "inboxes:drafts", "create", + "--inbox-id", "inbox_id", + ) + }) } func TestInboxesDraftsRetrieve(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:drafts", "retrieve", - "--api-key", "string", - "--inbox-id", "inbox_id", - "--draft-id", "draft_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:drafts", "retrieve", + "--inbox-id", "inbox_id", + "--draft-id", "draft_id", + ) + }) } func TestInboxesDraftsUpdate(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:drafts", "update", - "--api-key", "string", - "--inbox-id", "inbox_id", - "--draft-id", "draft_id", - "--bcc", "[string]", - "--cc", "[string]", - "--html", "html", - "--reply-to", "[string]", - "--send-at", "'2019-12-27T18:11:19.117Z'", - "--subject", "subject", - "--text", "text", - "--to", "[string]", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:drafts", "update", + "--inbox-id", "inbox_id", + "--draft-id", "draft_id", + "--bcc", "[string]", + "--cc", "[string]", + "--html", "html", + "--reply-to", "[string]", + "--send-at", "'2019-12-27T18:11:19.117Z'", + "--subject", "subject", + "--text", "text", + "--to", "[string]", + ) + }) + + t.Run("piping data", func(t *testing.T) { + // Test piping YAML data over stdin + pipeData := []byte("" + + "bcc:\n" + + " - string\n" + + "cc:\n" + + " - string\n" + + "html: html\n" + + "reply_to:\n" + + " - string\n" + + "send_at: '2019-12-27T18:11:19.117Z'\n" + + "subject: subject\n" + + "text: text\n" + + "to:\n" + + " - string\n") + mocktest.TestRunMockTestWithPipeAndFlags( + t, pipeData, + "--api-key", "string", + "inboxes:drafts", "update", + "--inbox-id", "inbox_id", + "--draft-id", "draft_id", + ) + }) } func TestInboxesDraftsList(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:drafts", "list", - "--api-key", "string", - "--inbox-id", "inbox_id", - "--after", "'2019-12-27T18:11:19.117Z'", - "--ascending=true", - "--before", "'2019-12-27T18:11:19.117Z'", - "--label", "[string]", - "--limit", "0", - "--page-token", "page_token", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:drafts", "list", + "--inbox-id", "inbox_id", + "--after", "'2019-12-27T18:11:19.117Z'", + "--ascending=true", + "--before", "'2019-12-27T18:11:19.117Z'", + "--label", "[string]", + "--limit", "0", + "--page-token", "page_token", + ) + }) } func TestInboxesDraftsDelete(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:drafts", "delete", - "--api-key", "string", - "--inbox-id", "inbox_id", - "--draft-id", "draft_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:drafts", "delete", + "--inbox-id", "inbox_id", + "--draft-id", "draft_id", + ) + }) } func TestInboxesDraftsSend(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:drafts", "send", - "--api-key", "string", - "--inbox-id", "inbox_id", - "--draft-id", "draft_id", - "--add-label", "[string]", - "--remove-label", "[string]", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:drafts", "send", + "--inbox-id", "inbox_id", + "--draft-id", "draft_id", + "--add-label", "[string]", + "--remove-label", "[string]", + ) + }) + + t.Run("piping data", func(t *testing.T) { + // Test piping YAML data over stdin + pipeData := []byte("" + + "add_labels:\n" + + " - string\n" + + "remove_labels:\n" + + " - string\n") + mocktest.TestRunMockTestWithPipeAndFlags( + t, pipeData, + "--api-key", "string", + "inboxes:drafts", "send", + "--inbox-id", "inbox_id", + "--draft-id", "draft_id", + ) + }) } diff --git a/pkg/cmd/inboxmessage.go b/pkg/cmd/inboxmessage.go index 62e255c..d3b5e2b 100644 --- a/pkg/cmd/inboxmessage.go +++ b/pkg/cmd/inboxmessage.go @@ -789,12 +789,22 @@ func handleInboxesMessagesGetRaw(ctx context.Context, cmd *cli.Command) error { return err } - return client.Inboxes.Messages.GetRaw( + var res []byte + options = append(options, option.WithResponseBodyInto(&res)) + _, err = client.Inboxes.Messages.GetRaw( ctx, cmd.Value("message-id").(string), params, options..., ) + if err != nil { + return err + } + + obj := gjson.ParseBytes(res) + format := cmd.Root().String("format") + transform := cmd.Root().String("transform") + return ShowJSON(os.Stdout, "inboxes:messages get-raw", obj, format, transform) } func handleInboxesMessagesReply(ctx context.Context, cmd *cli.Command) error { diff --git a/pkg/cmd/inboxmessage_test.go b/pkg/cmd/inboxmessage_test.go index bddb8bc..07016d7 100644 --- a/pkg/cmd/inboxmessage_test.go +++ b/pkg/cmd/inboxmessage_test.go @@ -11,244 +11,405 @@ import ( func TestInboxesMessagesRetrieve(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:messages", "retrieve", - "--api-key", "string", - "--inbox-id", "inbox_id", - "--message-id", "message_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:messages", "retrieve", + "--inbox-id", "inbox_id", + "--message-id", "message_id", + ) + }) } func TestInboxesMessagesUpdate(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:messages", "update", - "--api-key", "string", - "--inbox-id", "inbox_id", - "--message-id", "message_id", - "--add-label", "[string]", - "--remove-label", "[string]", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:messages", "update", + "--inbox-id", "inbox_id", + "--message-id", "message_id", + "--add-label", "[string]", + "--remove-label", "[string]", + ) + }) + + t.Run("piping data", func(t *testing.T) { + // Test piping YAML data over stdin + pipeData := []byte("" + + "add_labels:\n" + + " - string\n" + + "remove_labels:\n" + + " - string\n") + mocktest.TestRunMockTestWithPipeAndFlags( + t, pipeData, + "--api-key", "string", + "inboxes:messages", "update", + "--inbox-id", "inbox_id", + "--message-id", "message_id", + ) + }) } func TestInboxesMessagesList(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:messages", "list", - "--api-key", "string", - "--inbox-id", "inbox_id", - "--after", "'2019-12-27T18:11:19.117Z'", - "--ascending=true", - "--before", "'2019-12-27T18:11:19.117Z'", - "--include-blocked=true", - "--include-spam=true", - "--include-trash=true", - "--label", "[string]", - "--limit", "0", - "--page-token", "page_token", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:messages", "list", + "--inbox-id", "inbox_id", + "--after", "'2019-12-27T18:11:19.117Z'", + "--ascending=true", + "--before", "'2019-12-27T18:11:19.117Z'", + "--include-blocked=true", + "--include-spam=true", + "--include-trash=true", + "--label", "[string]", + "--limit", "0", + "--page-token", "page_token", + ) + }) } func TestInboxesMessagesForward(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:messages", "forward", - "--api-key", "string", - "--inbox-id", "inbox_id", - "--message-id", "message_id", - "--attachment", "[{content: content, content_disposition: inline, content_id: content_id, content_type: content_type, filename: filename, url: url}]", - "--bcc", "string", - "--cc", "string", - "--headers", "{foo: string}", - "--html", "html", - "--label", "[string]", - "--reply-to", "string", - "--subject", "subject", - "--text", "text", - "--to", "string", - ) - - // Check that inner flags have been set up correctly - requestflag.CheckInnerFlags(inboxesMessagesForward) - - // Alternative argument passing style using inner flags - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:messages", "forward", - "--inbox-id", "inbox_id", - "--message-id", "message_id", - "--attachment.content", "content", - "--attachment.content-disposition", "inline", - "--attachment.content-id", "content_id", - "--attachment.content-type", "content_type", - "--attachment.filename", "filename", - "--attachment.url", "url", - "--bcc", "string", - "--cc", "string", - "--headers", "{foo: string}", - "--html", "html", - "--label", "[string]", - "--reply-to", "string", - "--subject", "subject", - "--text", "text", - "--to", "string", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:messages", "forward", + "--inbox-id", "inbox_id", + "--message-id", "message_id", + "--attachment", "[{content: content, content_disposition: inline, content_id: content_id, content_type: content_type, filename: filename, url: url}]", + "--bcc", "string", + "--cc", "string", + "--headers", "{foo: string}", + "--html", "html", + "--label", "[string]", + "--reply-to", "string", + "--subject", "subject", + "--text", "text", + "--to", "string", + ) + }) + + t.Run("inner flags", func(t *testing.T) { + // Check that inner flags have been set up correctly + requestflag.CheckInnerFlags(inboxesMessagesForward) + + // Alternative argument passing style using inner flags + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:messages", "forward", + "--inbox-id", "inbox_id", + "--message-id", "message_id", + "--attachment.content", "content", + "--attachment.content-disposition", "inline", + "--attachment.content-id", "content_id", + "--attachment.content-type", "content_type", + "--attachment.filename", "filename", + "--attachment.url", "url", + "--bcc", "string", + "--cc", "string", + "--headers", "{foo: string}", + "--html", "html", + "--label", "[string]", + "--reply-to", "string", + "--subject", "subject", + "--text", "text", + "--to", "string", + ) + }) + + t.Run("piping data", func(t *testing.T) { + // Test piping YAML data over stdin + pipeData := []byte("" + + "attachments:\n" + + " - content: content\n" + + " content_disposition: inline\n" + + " content_id: content_id\n" + + " content_type: content_type\n" + + " filename: filename\n" + + " url: url\n" + + "bcc: string\n" + + "cc: string\n" + + "headers:\n" + + " foo: string\n" + + "html: html\n" + + "labels:\n" + + " - string\n" + + "reply_to: string\n" + + "subject: subject\n" + + "text: text\n" + + "to: string\n") + mocktest.TestRunMockTestWithPipeAndFlags( + t, pipeData, + "--api-key", "string", + "inboxes:messages", "forward", + "--inbox-id", "inbox_id", + "--message-id", "message_id", + ) + }) } func TestInboxesMessagesGetAttachment(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:messages", "get-attachment", - "--api-key", "string", - "--inbox-id", "inbox_id", - "--message-id", "message_id", - "--attachment-id", "attachment_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:messages", "get-attachment", + "--inbox-id", "inbox_id", + "--message-id", "message_id", + "--attachment-id", "attachment_id", + ) + }) } func TestInboxesMessagesGetRaw(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:messages", "get-raw", - "--api-key", "string", - "--inbox-id", "inbox_id", - "--message-id", "message_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:messages", "get-raw", + "--inbox-id", "inbox_id", + "--message-id", "message_id", + ) + }) } func TestInboxesMessagesReply(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:messages", "reply", - "--api-key", "string", - "--inbox-id", "inbox_id", - "--message-id", "message_id", - "--attachment", "[{content: content, content_disposition: inline, content_id: content_id, content_type: content_type, filename: filename, url: url}]", - "--bcc", "string", - "--cc", "string", - "--headers", "{foo: string}", - "--html", "html", - "--label", "[string]", - "--reply-all=true", - "--reply-to", "string", - "--text", "text", - "--to", "string", - ) - - // Check that inner flags have been set up correctly - requestflag.CheckInnerFlags(inboxesMessagesReply) - - // Alternative argument passing style using inner flags - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:messages", "reply", - "--inbox-id", "inbox_id", - "--message-id", "message_id", - "--attachment.content", "content", - "--attachment.content-disposition", "inline", - "--attachment.content-id", "content_id", - "--attachment.content-type", "content_type", - "--attachment.filename", "filename", - "--attachment.url", "url", - "--bcc", "string", - "--cc", "string", - "--headers", "{foo: string}", - "--html", "html", - "--label", "[string]", - "--reply-all=true", - "--reply-to", "string", - "--text", "text", - "--to", "string", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:messages", "reply", + "--inbox-id", "inbox_id", + "--message-id", "message_id", + "--attachment", "[{content: content, content_disposition: inline, content_id: content_id, content_type: content_type, filename: filename, url: url}]", + "--bcc", "string", + "--cc", "string", + "--headers", "{foo: string}", + "--html", "html", + "--label", "[string]", + "--reply-all=true", + "--reply-to", "string", + "--text", "text", + "--to", "string", + ) + }) + + t.Run("inner flags", func(t *testing.T) { + // Check that inner flags have been set up correctly + requestflag.CheckInnerFlags(inboxesMessagesReply) + + // Alternative argument passing style using inner flags + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:messages", "reply", + "--inbox-id", "inbox_id", + "--message-id", "message_id", + "--attachment.content", "content", + "--attachment.content-disposition", "inline", + "--attachment.content-id", "content_id", + "--attachment.content-type", "content_type", + "--attachment.filename", "filename", + "--attachment.url", "url", + "--bcc", "string", + "--cc", "string", + "--headers", "{foo: string}", + "--html", "html", + "--label", "[string]", + "--reply-all=true", + "--reply-to", "string", + "--text", "text", + "--to", "string", + ) + }) + + t.Run("piping data", func(t *testing.T) { + // Test piping YAML data over stdin + pipeData := []byte("" + + "attachments:\n" + + " - content: content\n" + + " content_disposition: inline\n" + + " content_id: content_id\n" + + " content_type: content_type\n" + + " filename: filename\n" + + " url: url\n" + + "bcc: string\n" + + "cc: string\n" + + "headers:\n" + + " foo: string\n" + + "html: html\n" + + "labels:\n" + + " - string\n" + + "reply_all: true\n" + + "reply_to: string\n" + + "text: text\n" + + "to: string\n") + mocktest.TestRunMockTestWithPipeAndFlags( + t, pipeData, + "--api-key", "string", + "inboxes:messages", "reply", + "--inbox-id", "inbox_id", + "--message-id", "message_id", + ) + }) } func TestInboxesMessagesReplyAll(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:messages", "reply-all", - "--api-key", "string", - "--inbox-id", "inbox_id", - "--message-id", "message_id", - "--attachment", "[{content: content, content_disposition: inline, content_id: content_id, content_type: content_type, filename: filename, url: url}]", - "--headers", "{foo: string}", - "--html", "html", - "--label", "[string]", - "--reply-to", "string", - "--text", "text", - ) - - // Check that inner flags have been set up correctly - requestflag.CheckInnerFlags(inboxesMessagesReplyAll) - - // Alternative argument passing style using inner flags - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:messages", "reply-all", - "--inbox-id", "inbox_id", - "--message-id", "message_id", - "--attachment.content", "content", - "--attachment.content-disposition", "inline", - "--attachment.content-id", "content_id", - "--attachment.content-type", "content_type", - "--attachment.filename", "filename", - "--attachment.url", "url", - "--headers", "{foo: string}", - "--html", "html", - "--label", "[string]", - "--reply-to", "string", - "--text", "text", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:messages", "reply-all", + "--inbox-id", "inbox_id", + "--message-id", "message_id", + "--attachment", "[{content: content, content_disposition: inline, content_id: content_id, content_type: content_type, filename: filename, url: url}]", + "--headers", "{foo: string}", + "--html", "html", + "--label", "[string]", + "--reply-to", "string", + "--text", "text", + ) + }) + + t.Run("inner flags", func(t *testing.T) { + // Check that inner flags have been set up correctly + requestflag.CheckInnerFlags(inboxesMessagesReplyAll) + + // Alternative argument passing style using inner flags + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:messages", "reply-all", + "--inbox-id", "inbox_id", + "--message-id", "message_id", + "--attachment.content", "content", + "--attachment.content-disposition", "inline", + "--attachment.content-id", "content_id", + "--attachment.content-type", "content_type", + "--attachment.filename", "filename", + "--attachment.url", "url", + "--headers", "{foo: string}", + "--html", "html", + "--label", "[string]", + "--reply-to", "string", + "--text", "text", + ) + }) + + t.Run("piping data", func(t *testing.T) { + // Test piping YAML data over stdin + pipeData := []byte("" + + "attachments:\n" + + " - content: content\n" + + " content_disposition: inline\n" + + " content_id: content_id\n" + + " content_type: content_type\n" + + " filename: filename\n" + + " url: url\n" + + "headers:\n" + + " foo: string\n" + + "html: html\n" + + "labels:\n" + + " - string\n" + + "reply_to: string\n" + + "text: text\n") + mocktest.TestRunMockTestWithPipeAndFlags( + t, pipeData, + "--api-key", "string", + "inboxes:messages", "reply-all", + "--inbox-id", "inbox_id", + "--message-id", "message_id", + ) + }) } func TestInboxesMessagesSend(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:messages", "send", - "--api-key", "string", - "--inbox-id", "inbox_id", - "--attachment", "[{content: content, content_disposition: inline, content_id: content_id, content_type: content_type, filename: filename, url: url}]", - "--bcc", "string", - "--cc", "string", - "--headers", "{foo: string}", - "--html", "html", - "--label", "[string]", - "--reply-to", "string", - "--subject", "subject", - "--text", "text", - "--to", "string", - ) - - // Check that inner flags have been set up correctly - requestflag.CheckInnerFlags(inboxesMessagesSend) - - // Alternative argument passing style using inner flags - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:messages", "send", - "--inbox-id", "inbox_id", - "--attachment.content", "content", - "--attachment.content-disposition", "inline", - "--attachment.content-id", "content_id", - "--attachment.content-type", "content_type", - "--attachment.filename", "filename", - "--attachment.url", "url", - "--bcc", "string", - "--cc", "string", - "--headers", "{foo: string}", - "--html", "html", - "--label", "[string]", - "--reply-to", "string", - "--subject", "subject", - "--text", "text", - "--to", "string", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:messages", "send", + "--inbox-id", "inbox_id", + "--attachment", "[{content: content, content_disposition: inline, content_id: content_id, content_type: content_type, filename: filename, url: url}]", + "--bcc", "string", + "--cc", "string", + "--headers", "{foo: string}", + "--html", "html", + "--label", "[string]", + "--reply-to", "string", + "--subject", "subject", + "--text", "text", + "--to", "string", + ) + }) + + t.Run("inner flags", func(t *testing.T) { + // Check that inner flags have been set up correctly + requestflag.CheckInnerFlags(inboxesMessagesSend) + + // Alternative argument passing style using inner flags + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:messages", "send", + "--inbox-id", "inbox_id", + "--attachment.content", "content", + "--attachment.content-disposition", "inline", + "--attachment.content-id", "content_id", + "--attachment.content-type", "content_type", + "--attachment.filename", "filename", + "--attachment.url", "url", + "--bcc", "string", + "--cc", "string", + "--headers", "{foo: string}", + "--html", "html", + "--label", "[string]", + "--reply-to", "string", + "--subject", "subject", + "--text", "text", + "--to", "string", + ) + }) + + t.Run("piping data", func(t *testing.T) { + // Test piping YAML data over stdin + pipeData := []byte("" + + "attachments:\n" + + " - content: content\n" + + " content_disposition: inline\n" + + " content_id: content_id\n" + + " content_type: content_type\n" + + " filename: filename\n" + + " url: url\n" + + "bcc: string\n" + + "cc: string\n" + + "headers:\n" + + " foo: string\n" + + "html: html\n" + + "labels:\n" + + " - string\n" + + "reply_to: string\n" + + "subject: subject\n" + + "text: text\n" + + "to: string\n") + mocktest.TestRunMockTestWithPipeAndFlags( + t, pipeData, + "--api-key", "string", + "inboxes:messages", "send", + "--inbox-id", "inbox_id", + ) + }) } diff --git a/pkg/cmd/inboxthread.go b/pkg/cmd/inboxthread.go index 9677e59..f9d68df 100644 --- a/pkg/cmd/inboxthread.go +++ b/pkg/cmd/inboxthread.go @@ -97,7 +97,7 @@ var inboxesThreadsList = cli.Command{ var inboxesThreadsDelete = cli.Command{ Name: "delete", - Usage: "Delete Thread", + Usage: "Moves the thread to trash by adding a trash label to all messages. If the thread\nis already in trash, it will be permanently deleted. Use `permanent=true` to\nforce permanent deletion.", Suggest: true, Flags: []cli.Flag{ &requestflag.Flag[string]{ @@ -110,6 +110,11 @@ var inboxesThreadsDelete = cli.Command{ Usage: "ID of thread.", Required: true, }, + &requestflag.Flag[any]{ + Name: "permanent", + Usage: "If true, permanently delete the thread instead of moving to trash.", + QueryPath: "permanent", + }, }, Action: handleInboxesThreadsDelete, HideHelpCommand: true, diff --git a/pkg/cmd/inboxthread_test.go b/pkg/cmd/inboxthread_test.go index e7ee260..0446dde 100644 --- a/pkg/cmd/inboxthread_test.go +++ b/pkg/cmd/inboxthread_test.go @@ -10,53 +10,62 @@ import ( func TestInboxesThreadsRetrieve(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:threads", "retrieve", - "--api-key", "string", - "--inbox-id", "inbox_id", - "--thread-id", "thread_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:threads", "retrieve", + "--inbox-id", "inbox_id", + "--thread-id", "thread_id", + ) + }) } func TestInboxesThreadsList(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:threads", "list", - "--api-key", "string", - "--inbox-id", "inbox_id", - "--after", "'2019-12-27T18:11:19.117Z'", - "--ascending=true", - "--before", "'2019-12-27T18:11:19.117Z'", - "--include-blocked=true", - "--include-spam=true", - "--include-trash=true", - "--label", "[string]", - "--limit", "0", - "--page-token", "page_token", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:threads", "list", + "--inbox-id", "inbox_id", + "--after", "'2019-12-27T18:11:19.117Z'", + "--ascending=true", + "--before", "'2019-12-27T18:11:19.117Z'", + "--include-blocked=true", + "--include-spam=true", + "--include-trash=true", + "--label", "[string]", + "--limit", "0", + "--page-token", "page_token", + ) + }) } func TestInboxesThreadsDelete(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:threads", "delete", - "--api-key", "string", - "--inbox-id", "inbox_id", - "--thread-id", "thread_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:threads", "delete", + "--inbox-id", "inbox_id", + "--thread-id", "thread_id", + "--permanent=true", + ) + }) } func TestInboxesThreadsGetAttachment(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "inboxes:threads", "get-attachment", - "--api-key", "string", - "--inbox-id", "inbox_id", - "--thread-id", "thread_id", - "--attachment-id", "attachment_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "inboxes:threads", "get-attachment", + "--inbox-id", "inbox_id", + "--thread-id", "thread_id", + "--attachment-id", "attachment_id", + ) + }) } diff --git a/pkg/cmd/metric.go b/pkg/cmd/metric.go index 908c16f..991f65b 100644 --- a/pkg/cmd/metric.go +++ b/pkg/cmd/metric.go @@ -17,26 +17,39 @@ import ( var metricsList = cli.Command{ Name: "list", - Usage: "List Metrics", + Usage: "Query Metrics", Suggest: true, Flags: []cli.Flag{ &requestflag.Flag[any]{ - Name: "end-timestamp", - Usage: "End timestamp for the metrics query range.", - Required: true, - QueryPath: "end_timestamp", + Name: "descending", + Usage: "Sort in descending order.", + QueryPath: "descending", }, &requestflag.Flag[any]{ - Name: "start-timestamp", - Usage: "Start timestamp for the metrics query range.", - Required: true, - QueryPath: "start_timestamp", + Name: "end", + Usage: "End timestamp for the query.", + QueryPath: "end", }, &requestflag.Flag[any]{ Name: "event-type", - Usage: "List of metric event types to filter by.", + Usage: "List of metric event types to query.", QueryPath: "event_types", }, + &requestflag.Flag[any]{ + Name: "limit", + Usage: "Limit on number of buckets to return.", + QueryPath: "limit", + }, + &requestflag.Flag[any]{ + Name: "period", + Usage: "Period in number of seconds for the query.", + QueryPath: "period", + }, + &requestflag.Flag[any]{ + Name: "start", + Usage: "Start timestamp for the query.", + QueryPath: "start", + }, }, Action: handleMetricsList, HideHelpCommand: true, diff --git a/pkg/cmd/metric_test.go b/pkg/cmd/metric_test.go index a7f25f4..6b2757a 100644 --- a/pkg/cmd/metric_test.go +++ b/pkg/cmd/metric_test.go @@ -10,12 +10,17 @@ import ( func TestMetricsList(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "metrics", "list", - "--api-key", "string", - "--end-timestamp", "'2019-12-27T18:11:19.117Z'", - "--start-timestamp", "'2019-12-27T18:11:19.117Z'", - "--event-type", "[message.sent]", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "metrics", "list", + "--descending=true", + "--end", "'2019-12-27T18:11:19.117Z'", + "--event-type", "[message.sent]", + "--limit", "0", + "--period", "period", + "--start", "'2019-12-27T18:11:19.117Z'", + ) + }) } diff --git a/pkg/cmd/organization_test.go b/pkg/cmd/organization_test.go index 4b65138..b041b23 100644 --- a/pkg/cmd/organization_test.go +++ b/pkg/cmd/organization_test.go @@ -10,9 +10,11 @@ import ( func TestOrganizationsRetrieve(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "organizations", "retrieve", - "--api-key", "string", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "organizations", "retrieve", + ) + }) } diff --git a/pkg/cmd/pod_test.go b/pkg/cmd/pod_test.go index d76639b..2146d93 100644 --- a/pkg/cmd/pod_test.go +++ b/pkg/cmd/pod_test.go @@ -10,43 +10,63 @@ import ( func TestPodsCreate(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "pods", "create", - "--api-key", "string", - "--client-id", "client_id", - "--name", "name", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "pods", "create", + "--client-id", "client_id", + "--name", "name", + ) + }) + + t.Run("piping data", func(t *testing.T) { + // Test piping YAML data over stdin + pipeData := []byte("" + + "client_id: client_id\n" + + "name: name\n") + mocktest.TestRunMockTestWithPipeAndFlags( + t, pipeData, + "--api-key", "string", + "pods", "create", + ) + }) } func TestPodsRetrieve(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "pods", "retrieve", - "--api-key", "string", - "--pod-id", "pod_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "pods", "retrieve", + "--pod-id", "pod_id", + ) + }) } func TestPodsList(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "pods", "list", - "--api-key", "string", - "--ascending=true", - "--limit", "0", - "--page-token", "page_token", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "pods", "list", + "--ascending=true", + "--limit", "0", + "--page-token", "page_token", + ) + }) } func TestPodsDelete(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "pods", "delete", - "--api-key", "string", - "--pod-id", "pod_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "pods", "delete", + "--pod-id", "pod_id", + ) + }) } diff --git a/pkg/cmd/poddomain.go b/pkg/cmd/poddomain.go index efc7307..c4cb094 100644 --- a/pkg/cmd/poddomain.go +++ b/pkg/cmd/poddomain.go @@ -27,7 +27,7 @@ var podsDomainsCreate = cli.Command{ }, &requestflag.Flag[string]{ Name: "domain", - Usage: `The name of the domain. (e.g., "example.com")`, + Usage: "The name of the domain (e.g., `example.com`).", Required: true, BodyPath: "domain", }, @@ -84,7 +84,7 @@ var podsDomainsDelete = cli.Command{ }, &requestflag.Flag[string]{ Name: "domain-id", - Usage: `The name of the domain. (e.g., " your-domain.com")`, + Usage: "The ID of the domain.", Required: true, }, }, diff --git a/pkg/cmd/poddomain_test.go b/pkg/cmd/poddomain_test.go index a782d61..fde87f5 100644 --- a/pkg/cmd/poddomain_test.go +++ b/pkg/cmd/poddomain_test.go @@ -10,36 +10,55 @@ import ( func TestPodsDomainsCreate(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "pods:domains", "create", - "--api-key", "string", - "--pod-id", "pod_id", - "--domain", "domain", - "--feedback-enabled=true", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "pods:domains", "create", + "--pod-id", "pod_id", + "--domain", "domain", + "--feedback-enabled=true", + ) + }) + + t.Run("piping data", func(t *testing.T) { + // Test piping YAML data over stdin + pipeData := []byte("" + + "domain: domain\n" + + "feedback_enabled: true\n") + mocktest.TestRunMockTestWithPipeAndFlags( + t, pipeData, + "--api-key", "string", + "pods:domains", "create", + "--pod-id", "pod_id", + ) + }) } func TestPodsDomainsList(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "pods:domains", "list", - "--api-key", "string", - "--pod-id", "pod_id", - "--ascending=true", - "--limit", "0", - "--page-token", "page_token", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "pods:domains", "list", + "--pod-id", "pod_id", + "--ascending=true", + "--limit", "0", + "--page-token", "page_token", + ) + }) } func TestPodsDomainsDelete(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "pods:domains", "delete", - "--api-key", "string", - "--pod-id", "pod_id", - "--domain-id", "domain_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "pods:domains", "delete", + "--pod-id", "pod_id", + "--domain-id", "domain_id", + ) + }) } diff --git a/pkg/cmd/poddraft_test.go b/pkg/cmd/poddraft_test.go index 460706c..ea6a65a 100644 --- a/pkg/cmd/poddraft_test.go +++ b/pkg/cmd/poddraft_test.go @@ -10,27 +10,31 @@ import ( func TestPodsDraftsRetrieve(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "pods:drafts", "retrieve", - "--api-key", "string", - "--pod-id", "pod_id", - "--draft-id", "draft_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "pods:drafts", "retrieve", + "--pod-id", "pod_id", + "--draft-id", "draft_id", + ) + }) } func TestPodsDraftsList(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "pods:drafts", "list", - "--api-key", "string", - "--pod-id", "pod_id", - "--after", "'2019-12-27T18:11:19.117Z'", - "--ascending=true", - "--before", "'2019-12-27T18:11:19.117Z'", - "--label", "[string]", - "--limit", "0", - "--page-token", "page_token", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "pods:drafts", "list", + "--pod-id", "pod_id", + "--after", "'2019-12-27T18:11:19.117Z'", + "--ascending=true", + "--before", "'2019-12-27T18:11:19.117Z'", + "--label", "[string]", + "--limit", "0", + "--page-token", "page_token", + ) + }) } diff --git a/pkg/cmd/podinbox_test.go b/pkg/cmd/podinbox_test.go index 83fb056..53cbb5b 100644 --- a/pkg/cmd/podinbox_test.go +++ b/pkg/cmd/podinbox_test.go @@ -10,49 +10,72 @@ import ( func TestPodsInboxesCreate(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "pods:inboxes", "create", - "--api-key", "string", - "--pod-id", "pod_id", - "--client-id", "client_id", - "--display-name", "display_name", - "--domain", "domain", - "--username", "username", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "pods:inboxes", "create", + "--pod-id", "pod_id", + "--client-id", "client_id", + "--display-name", "display_name", + "--domain", "domain", + "--username", "username", + ) + }) + + t.Run("piping data", func(t *testing.T) { + // Test piping YAML data over stdin + pipeData := []byte("" + + "client_id: client_id\n" + + "display_name: display_name\n" + + "domain: domain\n" + + "username: username\n") + mocktest.TestRunMockTestWithPipeAndFlags( + t, pipeData, + "--api-key", "string", + "pods:inboxes", "create", + "--pod-id", "pod_id", + ) + }) } func TestPodsInboxesRetrieve(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "pods:inboxes", "retrieve", - "--api-key", "string", - "--pod-id", "pod_id", - "--inbox-id", "inbox_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "pods:inboxes", "retrieve", + "--pod-id", "pod_id", + "--inbox-id", "inbox_id", + ) + }) } func TestPodsInboxesList(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "pods:inboxes", "list", - "--api-key", "string", - "--pod-id", "pod_id", - "--ascending=true", - "--limit", "0", - "--page-token", "page_token", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "pods:inboxes", "list", + "--pod-id", "pod_id", + "--ascending=true", + "--limit", "0", + "--page-token", "page_token", + ) + }) } func TestPodsInboxesDelete(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "pods:inboxes", "delete", - "--api-key", "string", - "--pod-id", "pod_id", - "--inbox-id", "inbox_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "pods:inboxes", "delete", + "--pod-id", "pod_id", + "--inbox-id", "inbox_id", + ) + }) } diff --git a/pkg/cmd/podthread_test.go b/pkg/cmd/podthread_test.go index 9ef77ed..311603b 100644 --- a/pkg/cmd/podthread_test.go +++ b/pkg/cmd/podthread_test.go @@ -10,42 +10,48 @@ import ( func TestPodsThreadsRetrieve(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "pods:threads", "retrieve", - "--api-key", "string", - "--pod-id", "pod_id", - "--thread-id", "thread_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "pods:threads", "retrieve", + "--pod-id", "pod_id", + "--thread-id", "thread_id", + ) + }) } func TestPodsThreadsList(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "pods:threads", "list", - "--api-key", "string", - "--pod-id", "pod_id", - "--after", "'2019-12-27T18:11:19.117Z'", - "--ascending=true", - "--before", "'2019-12-27T18:11:19.117Z'", - "--include-blocked=true", - "--include-spam=true", - "--include-trash=true", - "--label", "[string]", - "--limit", "0", - "--page-token", "page_token", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "pods:threads", "list", + "--pod-id", "pod_id", + "--after", "'2019-12-27T18:11:19.117Z'", + "--ascending=true", + "--before", "'2019-12-27T18:11:19.117Z'", + "--include-blocked=true", + "--include-spam=true", + "--include-trash=true", + "--label", "[string]", + "--limit", "0", + "--page-token", "page_token", + ) + }) } func TestPodsThreadsGetAttachment(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "pods:threads", "get-attachment", - "--api-key", "string", - "--pod-id", "pod_id", - "--thread-id", "thread_id", - "--attachment-id", "attachment_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "pods:threads", "get-attachment", + "--pod-id", "pod_id", + "--thread-id", "thread_id", + "--attachment-id", "attachment_id", + ) + }) } diff --git a/pkg/cmd/thread.go b/pkg/cmd/thread.go index 0721994..8dc42be 100644 --- a/pkg/cmd/thread.go +++ b/pkg/cmd/thread.go @@ -60,6 +60,11 @@ var threadsList = cli.Command{ Usage: "Include spam in results.", QueryPath: "include_spam", }, + &requestflag.Flag[any]{ + Name: "include-trash", + Usage: "Include trash in results.", + QueryPath: "include_trash", + }, &requestflag.Flag[any]{ Name: "label", Usage: "Labels to filter by.", diff --git a/pkg/cmd/thread_test.go b/pkg/cmd/thread_test.go index c476808..6053f05 100644 --- a/pkg/cmd/thread_test.go +++ b/pkg/cmd/thread_test.go @@ -10,38 +10,45 @@ import ( func TestThreadsRetrieve(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "threads", "retrieve", - "--api-key", "string", - "--thread-id", "thread_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "threads", "retrieve", + "--thread-id", "thread_id", + ) + }) } func TestThreadsList(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "threads", "list", - "--api-key", "string", - "--after", "'2019-12-27T18:11:19.117Z'", - "--ascending=true", - "--before", "'2019-12-27T18:11:19.117Z'", - "--include-blocked=true", - "--include-spam=true", - "--label", "[string]", - "--limit", "0", - "--page-token", "page_token", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "threads", "list", + "--after", "'2019-12-27T18:11:19.117Z'", + "--ascending=true", + "--before", "'2019-12-27T18:11:19.117Z'", + "--include-blocked=true", + "--include-spam=true", + "--include-trash=true", + "--label", "[string]", + "--limit", "0", + "--page-token", "page_token", + ) + }) } func TestThreadsRetrieveAttachment(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "threads", "retrieve-attachment", - "--api-key", "string", - "--thread-id", "thread_id", - "--attachment-id", "attachment_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "threads", "retrieve-attachment", + "--thread-id", "thread_id", + "--attachment-id", "attachment_id", + ) + }) } diff --git a/pkg/cmd/version.go b/pkg/cmd/version.go index 5c28322..b99b193 100644 --- a/pkg/cmd/version.go +++ b/pkg/cmd/version.go @@ -2,4 +2,4 @@ package cmd -const Version = "0.7.1" // x-release-please-version +const Version = "0.7.2" // x-release-please-version diff --git a/pkg/cmd/webhook_test.go b/pkg/cmd/webhook_test.go index 5e3fa4c..c5c33d6 100644 --- a/pkg/cmd/webhook_test.go +++ b/pkg/cmd/webhook_test.go @@ -10,60 +10,107 @@ import ( func TestWebhooksCreate(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "webhooks", "create", - "--api-key", "string", - "--event-type", "message.received", - "--url", "url", - "--client-id", "client_id", - "--inbox-id", "[string]", - "--pod-id", "[string]", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "webhooks", "create", + "--event-type", "message.received", + "--url", "url", + "--client-id", "client_id", + "--inbox-id", "[string]", + "--pod-id", "[string]", + ) + }) + + t.Run("piping data", func(t *testing.T) { + // Test piping YAML data over stdin + pipeData := []byte("" + + "event_types:\n" + + " - message.received\n" + + "url: url\n" + + "client_id: client_id\n" + + "inbox_ids:\n" + + " - string\n" + + "pod_ids:\n" + + " - string\n") + mocktest.TestRunMockTestWithPipeAndFlags( + t, pipeData, + "--api-key", "string", + "webhooks", "create", + ) + }) } func TestWebhooksRetrieve(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "webhooks", "retrieve", - "--api-key", "string", - "--webhook-id", "webhook_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "webhooks", "retrieve", + "--webhook-id", "webhook_id", + ) + }) } func TestWebhooksUpdate(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "webhooks", "update", - "--api-key", "string", - "--webhook-id", "webhook_id", - "--add-inbox-id", "[string]", - "--add-pod-id", "[string]", - "--remove-inbox-id", "[string]", - "--remove-pod-id", "[string]", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "webhooks", "update", + "--webhook-id", "webhook_id", + "--add-inbox-id", "[string]", + "--add-pod-id", "[string]", + "--remove-inbox-id", "[string]", + "--remove-pod-id", "[string]", + ) + }) + + t.Run("piping data", func(t *testing.T) { + // Test piping YAML data over stdin + pipeData := []byte("" + + "add_inbox_ids:\n" + + " - string\n" + + "add_pod_ids:\n" + + " - string\n" + + "remove_inbox_ids:\n" + + " - string\n" + + "remove_pod_ids:\n" + + " - string\n") + mocktest.TestRunMockTestWithPipeAndFlags( + t, pipeData, + "--api-key", "string", + "webhooks", "update", + "--webhook-id", "webhook_id", + ) + }) } func TestWebhooksList(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "webhooks", "list", - "--api-key", "string", - "--ascending=true", - "--limit", "0", - "--page-token", "page_token", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "webhooks", "list", + "--ascending=true", + "--limit", "0", + "--page-token", "page_token", + ) + }) } func TestWebhooksDelete(t *testing.T) { t.Skip("Mock server tests are disabled") - mocktest.TestRunMockTestWithFlags( - t, - "webhooks", "delete", - "--api-key", "string", - "--webhook-id", "webhook_id", - ) + t.Run("regular flags", func(t *testing.T) { + mocktest.TestRunMockTestWithFlags( + t, + "--api-key", "string", + "webhooks", "delete", + "--webhook-id", "webhook_id", + ) + }) } diff --git a/scripts/bootstrap b/scripts/bootstrap index d94c7d1..9ebb7d3 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -18,6 +18,5 @@ if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] echo } fi - echo "==> Installing Go dependencies…" -go mod tidy +go mod tidy -e || true diff --git a/scripts/build b/scripts/build index 82d9650..9b52c4a 100755 --- a/scripts/build +++ b/scripts/build @@ -1,8 +1,11 @@ #!/usr/bin/env bash -set -e +set -euo pipefail cd "$(dirname "$0")/.." +# Mark the necessary Go modules as private to avoid Go's proxy +export GOPRIVATE="${GOPRIVATE:+$GOPRIVATE,}github.com/agentmail-to/agentmail-go,github.com/stainless-sdks/agentmail-go" + echo "==> Building agentmail" go build ./cmd/agentmail diff --git a/scripts/link b/scripts/link index ef3a4e1..e6dac01 100755 --- a/scripts/link +++ b/scripts/link @@ -1,16 +1,13 @@ #!/usr/bin/env bash -set -e +set -euo pipefail cd "$(dirname "$0")/.." -if [[ -n "$1" ]]; then - LOCAL_GO="$1" - shift -else - LOCAL_GO=../agentmail-go -fi +# Mark the necessary Go modules as private to avoid Go's proxy +export GOPRIVATE="${GOPRIVATE:+$GOPRIVATE,}github.com/agentmail-to/agentmail-go,github.com/stainless-sdks/agentmail-go" -echo "==> Linking with local directory" +REPLACEMENT="${1:-"../agentmail-go"}" +echo "==> Replacing Go SDK with $REPLACEMENT" +go mod edit -replace github.com/agentmail-to/agentmail-go="$REPLACEMENT" go mod tidy -e -go mod edit -replace github.com/agentmail-to/agentmail-go="$LOCAL_GO" diff --git a/scripts/lint b/scripts/lint index fa7ba1f..0854d39 100755 --- a/scripts/lint +++ b/scripts/lint @@ -1,8 +1,11 @@ #!/usr/bin/env bash -set -e +set -euo pipefail cd "$(dirname "$0")/.." +# Mark the necessary Go modules as private to avoid Go's proxy +export GOPRIVATE="${GOPRIVATE:+$GOPRIVATE,}github.com/agentmail-to/agentmail-go,github.com/stainless-sdks/agentmail-go" + echo "==> Running Go build" go build ./... diff --git a/scripts/run b/scripts/run index 6fa4471..3df1082 100755 --- a/scripts/run +++ b/scripts/run @@ -1,7 +1,10 @@ #!/usr/bin/env bash -set -e +set -euo pipefail cd "$(dirname "$0")/.." +# Mark the necessary Go modules as private to avoid Go's proxy +export GOPRIVATE="${GOPRIVATE:+$GOPRIVATE,}github.com/agentmail-to/agentmail-go,github.com/stainless-sdks/agentmail-go" + go run ./cmd/agentmail "$@" diff --git a/scripts/test b/scripts/test index df2bd61..6e608db 100755 --- a/scripts/test +++ b/scripts/test @@ -4,6 +4,9 @@ set -euo pipefail cd "$(dirname "$0")/.." +# Mark the necessary Go modules as private to avoid Go's proxy +export GOPRIVATE="${GOPRIVATE:+$GOPRIVATE,}github.com/agentmail-to/agentmail-go,github.com/stainless-sdks/agentmail-go" + echo "==> Running tests"