diff --git a/commandline/parameter_formatter.go b/commandline/parameter_formatter.go index a6b3b10..77fe110 100644 --- a/commandline/parameter_formatter.go +++ b/commandline/parameter_formatter.go @@ -2,6 +2,7 @@ package commandline import ( "fmt" + "slices" "strings" "github.com/UiPath/uipathcli/parser" @@ -66,28 +67,31 @@ func (f parameterFormatter) descriptionFields(parameter parser.Parameter) []inte } func (f parameterFormatter) usageExample(parameter parser.Parameter) string { - parameters := map[string]string{} - f.collectUsageParameters(parameter, "", parameters) + parameters := f.collectUsageParameters(parameter, "") + slices.Sort(parameters) builder := strings.Builder{} - for key, value := range parameters { + for _, value := range parameters { f.writeSeparator(&builder, "; ") - builder.WriteString(fmt.Sprintf("%s=%s", key, value)) + builder.WriteString(value) } return builder.String() } -func (f parameterFormatter) collectUsageParameters(parameter parser.Parameter, prefix string, result map[string]string) { +func (f parameterFormatter) collectUsageParameters(parameter parser.Parameter, prefix string) []string { + result := []string{} for _, p := range parameter.Parameters { if p.Type == parser.ParameterTypeObjectArray { - f.collectUsageParameters(p, prefix+p.FieldName+"[0].", result) - continue + result = append(result, f.collectUsageParameters(p, prefix+p.FieldName+"[0].")...) + } else if p.Type == parser.ParameterTypeObject { + result = append(result, f.collectUsageParameters(p, prefix+p.FieldName+".")...) + } else { + field := prefix + p.FieldName + fieldType := f.humanReadableType(p.Type) + result = append(result, fmt.Sprintf("%s=%s", field, fieldType)) } - if p.Type == parser.ParameterTypeObject { - f.collectUsageParameters(p, prefix+p.FieldName+".", result) - } - result[prefix+p.FieldName] = f.humanReadableType(p.Type) } + return result } func (f parameterFormatter) commaSeparatedValues(values []interface{}) string { diff --git a/test/parser_test.go b/test/parser_test.go index aefadb2..6c656ea 100644 --- a/test/parser_test.go +++ b/test/parser_test.go @@ -1430,3 +1430,103 @@ paths: t.Errorf("Should not parse versioned service operation, but got: %v", result.StdOut) } } + +func TestShowsExampleOutputForObjects(t *testing.T) { + definition := ` +paths: + /create: + post: + operationId: create + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/CreateDeploymentRequest' +components: + schemas: + CreateDeploymentRequest: + type: object + properties: + config: + $ref: '#/components/schemas/DeploymentConfigModel' + DeploymentConfigModel: + type: object + properties: + cpu: + type: integer + format: int32 + memory: + type: number + format: double + gpu: + type: boolean +` + + context := NewContextBuilder(). + WithDefinition("myservice", definition). + Build() + + result := RunCli([]string{"myservice", "create", "--help"}, context) + + if !strings.Contains(result.StdOut, "Example:") { + t.Errorf("Could not find example output, but got: %v", result.StdOut) + } + if !strings.Contains(result.StdOut, "cpu=integer; gpu=boolean; memory=float") { + t.Errorf("Could not find example command, but got: %v", result.StdOut) + } +} + +func TestShowsExampleOutputForNestedObjects(t *testing.T) { + definition := ` +paths: + /create: + post: + operationId: create + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/CreateDeploymentRequest' +components: + schemas: + CreateDeploymentRequest: + type: object + properties: + instances: + type: array + items: + $ref: '#/components/schemas/DeploymentInstance' + DeploymentInstance: + type: object + properties: + config: + $ref: '#/components/schemas/DeploymentConfigModel' + DeploymentConfigModel: + type: object + properties: + cpu: + type: integer + format: int32 + memory: + type: number + format: double + gpu: + type: boolean +` + + context := NewContextBuilder(). + WithDefinition("myservice", definition). + Build() + + result := RunCli([]string{"myservice", "create", "--help"}, context) + + if !strings.Contains(result.StdOut, "Example:") { + t.Errorf("Could not find example output, but got: %v", result.StdOut) + } + if !strings.Contains(result.StdOut, "config.cpu=integer; config.gpu=boolean; config.memory=float") { + t.Errorf("Could not find example command, but got: %v", result.StdOut) + } + if strings.Contains(result.StdOut, "config=object") { + t.Errorf("Should not contain the object itself in the example, but got: %v", result.StdOut) + } +}