From 6abffce4e5e8f8e79b87629df6c8334255f37019 Mon Sep 17 00:00:00 2001 From: xiatian Date: Thu, 13 Aug 2026 16:13:30 +0800 Subject: [PATCH] fix(sheet): preserve dropdown schema compatibility --- internal/helpers/sheet_dimension.go | 6 --- .../sheet_dropdown_source_range_test.go | 49 ++++++++++++++----- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/internal/helpers/sheet_dimension.go b/internal/helpers/sheet_dimension.go index 2b442f02..1b902cc6 100644 --- a/internal/helpers/sheet_dimension.go +++ b/internal/helpers/sheet_dimension.go @@ -907,7 +907,6 @@ sheetId 支持传入工作表 ID 或工作表名称,可通过 sheet list 获 Parameters: []contract.ParamDecl{ {Name: "multi-select", Property: "enableMultiSelect"}, {Name: "node", Property: "nodeId"}, - {Name: "options", Property: "options", Required: boolPtr(false), RequiredWhen: "exactly one of --options or --source-range must be provided"}, {Name: "source-sheet-id", Property: "sourceRange.sheetId", Required: boolPtr(false), RequiredWhen: "--source-range is provided"}, {Name: "source-range", Property: "sourceRange.a1Notation", Required: boolPtr(false), RequiredWhen: "exactly one of --options or --source-range must be provided"}, }, @@ -924,11 +923,6 @@ sheetId 支持传入工作表 ID 或工作表名称,可通过 sheet list 获 setDropdownCmd.MarkFlagsOneRequired("options", "source-range") setDropdownCmd.MarkFlagsMutuallyExclusive("options", "source-range") setDropdownCmd.MarkFlagsRequiredTogether("source-sheet-id", "source-range") - cli.AnnotateRuntimeConstraints(setDropdownCmd, cli.RuntimeSchemaConstraints{ - MutuallyExclusive: [][]string{{"options", "source-range"}}, - RequireOneOf: [][]string{{"options", "source-range"}}, - RequireTogether: [][]string{{"source-sheet-id", "source-range"}}, - }) getDropdownCmd := &cobra.Command{ Use: "get-dropdown", diff --git a/internal/helpers/sheet_dropdown_source_range_test.go b/internal/helpers/sheet_dropdown_source_range_test.go index af7c1eeb..071e8ba4 100644 --- a/internal/helpers/sheet_dropdown_source_range_test.go +++ b/internal/helpers/sheet_dropdown_source_range_test.go @@ -1,7 +1,6 @@ package helpers import ( - "encoding/json" "strings" "testing" @@ -92,18 +91,43 @@ func TestCrossPlatformCoverageSetDropdownModeConstraints(t *testing.T) { } } -func TestCrossPlatformCoverageSetDropdownSchemaConstraints(t *testing.T) { - cmd := dimensionCoverageCommand(t, "set-dropdown") - constraints := runtimeannotate.CommandConstraints(cmd) - want := runtimeannotate.RuntimeSchemaConstraints{ - MutuallyExclusive: [][]string{{"options", "source-range"}}, - RequireOneOf: [][]string{{"options", "source-range"}}, - RequireTogether: [][]string{{"source-sheet-id", "source-range"}}, +func TestCrossPlatformCoverageSetDropdownRunEValidation(t *testing.T) { + tests := []struct { + name string + options string + source string + rangeID string + want string + }{ + {name: "neither mode", want: "必须且只能指定一个"}, + {name: "source range without sheet", rangeID: "A1:A3", want: "必须同时指定 --source-sheet-id"}, + {name: "source sheet without range", options: `[{"value":"one"}]`, source: "source", want: "必须同时指定 --source-range"}, + {name: "invalid options JSON", options: "{", want: "JSON 解析失败"}, + {name: "missing option value", options: `[{}]`, want: "value 为空"}, } - gotJSON, _ := json.Marshal(constraints) - wantJSON, _ := json.Marshal(runtimeannotate.NormalizeConstraints(want)) - if string(gotJSON) != string(wantJSON) { - t.Fatalf("constraints = %s, want %s", gotJSON, wantJSON) + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + cmd := dimensionCoverageCommand(t, "set-dropdown") + for name, value := range map[string]string{ + "node": "node", "sheet-id": "sheet", "range": "A1", + "options": tc.options, "source-sheet-id": tc.source, "source-range": tc.rangeID, + } { + if err := cmd.Flags().Set(name, value); err != nil { + t.Fatalf("set --%s: %v", name, err) + } + } + err := cmd.RunE(cmd, nil) + if err == nil || !strings.Contains(err.Error(), tc.want) { + t.Fatalf("error = %v, want contains %q", err, tc.want) + } + }) + } +} + +func TestCrossPlatformCoverageSetDropdownPreservesSchemaConstraints(t *testing.T) { + cmd := dimensionCoverageCommand(t, "set-dropdown") + if constraints := runtimeannotate.CommandConstraints(cmd); !runtimeannotate.ConstraintsEmpty(constraints) { + t.Fatalf("constraints = %#v, want no new schema-level constraints", constraints) } } @@ -135,6 +159,7 @@ func TestCrossPlatformCoverageBatchSetDropdownSourceRange(t *testing.T) { {"options": []any{map[string]any{"value": "one"}}, "source-sheet-id": "source", "source-range": "A1:A3"}, {"source-range": "A1:A3"}, {"source-sheet-id": "source", "source-range": "A1:A3", "colors": []any{"#fff"}}, + {"source-sheet-id": "source", "source-range": "A1:A3", "source-colors": []any{"#fff"}}, {"source-sheet-id": "source", "source-range": "Sheet2!A1:A3"}, } for _, value := range invalid {