mirror of
https://github.com/larksuite/cli.git
synced 2026-07-07 00:55:53 +08:00
* fix(api): add stdin and single-quote support for --params/--data on Windows (#64) Windows PowerShell 5.x mangles JSON double-quotes when passing arguments to native executables, causing --params and --data to fail with "invalid JSON format". This commit adds two mitigations at the framework level: - stdin piping: `echo '{"k":"v"}' | lark-cli --params -` bypasses shell argument parsing entirely and works on all platforms/shells. - single-quote stripping: cmd.exe passes literal single quotes which are now transparently removed before JSON parsing. Implementation: - New `cmdutil.ResolveInput(raw, stdin)` handles `-` (stdin), strip surrounding `'...'`, and plain passthrough. - `ParseJSONMap` and `ParseOptionalBody` now accept an `io.Reader` and delegate to `ResolveInput` before JSON unmarshalling. - `cmd/api` and `cmd/service` pass `IOStreams.In` and guard against simultaneous stdin usage by --params and --data. - Empty stdin is rejected with a clear error message. Closes #64 Change-Id: If21e735d0aed5c6a2d6674c1e6c898186fca3aba * test: add stdin e2e regression coverage Change-Id: I4e00bf1c6b6f3259f503e3414cae10fa4b34ba75
67 lines
1.8 KiB
Go
67 lines
1.8 KiB
Go
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package cmdutil
|
|
|
|
import "testing"
|
|
|
|
func TestParseOptionalBody(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
method string
|
|
data string
|
|
wantNil bool
|
|
wantErr bool
|
|
}{
|
|
{"GET ignored", "GET", `{"a":1}`, true, false},
|
|
{"POST empty data", "POST", "", true, false},
|
|
{"POST valid", "POST", `{"key":"val"}`, false, false},
|
|
{"PUT valid", "PUT", `[1,2,3]`, false, false},
|
|
{"PATCH valid", "PATCH", `"hello"`, false, false},
|
|
{"DELETE valid", "DELETE", `{"id":"1"}`, false, false},
|
|
{"POST invalid json", "POST", `{bad}`, true, true},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := ParseOptionalBody(tt.method, tt.data, nil)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("ParseOptionalBody() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if tt.wantNil && got != nil {
|
|
t.Errorf("ParseOptionalBody() = %v, want nil", got)
|
|
}
|
|
if !tt.wantNil && !tt.wantErr && got == nil {
|
|
t.Error("ParseOptionalBody() = nil, want non-nil")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseJSONMap(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
label string
|
|
wantLen int
|
|
wantErr bool
|
|
}{
|
|
{"empty input", "", "--params", 0, false},
|
|
{"valid json", `{"a":"1","b":"2"}`, "--params", 2, false},
|
|
{"invalid json", `{bad}`, "--params", 0, true},
|
|
{"json array", `[1,2]`, "--data", 0, true},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := ParseJSONMap(tt.input, tt.label, nil)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("ParseJSONMap() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if !tt.wantErr && len(got) != tt.wantLen {
|
|
t.Errorf("ParseJSONMap() returned map with %d keys, want %d", len(got), tt.wantLen)
|
|
}
|
|
})
|
|
}
|
|
}
|