From ee8d8fd941a36860639ef84c7dcb80dbc9884bd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=85=B4=E7=82=80?= Date: Tue, 7 Jul 2026 21:25:50 +0800 Subject: [PATCH] test(apps): cover no-env dry-run defaults + numericAsFloat string path Address CodeRabbit review threads on PR #1735: - numericAsFloat: add numeric-string cases ("13.5", " 13.5 ", int, empty) - db-data-import: assert dry-run omits env when --environment unset (table still defaults to file basename) - db-quota-get: assert dry-run omits env when --environment unset --- shortcuts/apps/apps_db_data_import_test.go | 25 +++++++++++++++++++ .../apps/apps_db_env_recovery_quota_test.go | 25 +++++++++++++++++++ shortcuts/apps/apps_db_table_list_test.go | 6 ++++- 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/shortcuts/apps/apps_db_data_import_test.go b/shortcuts/apps/apps_db_data_import_test.go index 0902e2cf1..2eb0388f6 100644 --- a/shortcuts/apps/apps_db_data_import_test.go +++ b/shortcuts/apps/apps_db_data_import_test.go @@ -121,6 +121,31 @@ func TestAppsDBDataImport_DryRunMultipartShape(t *testing.T) { } } +// TestAppsDBDataImport_DryRunOmitsEnvWhenUnset 验证不传 --environment 时 dry-run 的 query +// 不带 env 键(交服务端按应用形态自动选分支),但仍携带 table。 +func TestAppsDBDataImport_DryRunOmitsEnvWhenUnset(t *testing.T) { + chdirTemp(t) + _ = os.WriteFile("orders.csv", []byte("id\n1\n"), 0o600) + factory, stdout, _ := newAppsExecuteFactory(t) + if err := runAppsShortcut(t, AppsDBDataImport, + []string{"+db-data-import", "--app-id", "app_x", "--file", "orders.csv", "--dry-run", "--yes", "--as", "user"}, factory, stdout); err != nil { + t.Fatalf("dry-run err=%v", err) + } + var env struct { + API []struct { + Params map[string]interface{} `json:"params"` + } `json:"api"` + } + _ = json.Unmarshal([]byte(stdout.String()), &env) + p := env.API[0].Params + if _, ok := p["env"]; ok { + t.Fatalf("no --environment → env key must be omitted, got params=%v", p) + } + if p["table"] != "orders" { + t.Fatalf("table should still default to file basename, got params=%v", p) + } +} + // TestAppsDBDataImport_Success 验证成功导入后输出含 table、rows 与回显的 file 名。 func TestAppsDBDataImport_Success(t *testing.T) { chdirTemp(t) diff --git a/shortcuts/apps/apps_db_env_recovery_quota_test.go b/shortcuts/apps/apps_db_env_recovery_quota_test.go index 30edad30d..013f37bba 100644 --- a/shortcuts/apps/apps_db_env_recovery_quota_test.go +++ b/shortcuts/apps/apps_db_env_recovery_quota_test.go @@ -323,6 +323,31 @@ func TestAppsDBQuotaGet_WithQuotaPretty(t *testing.T) { } // 配额未对接(storage_quota_bytes=0)→ json 删 quota/usage_percent,仅留已用量与 tables/views。 +// TestAppsDBQuotaGet_DryRunOmitsEnvWhenUnset 验证不传 --environment 时 quota-get 的 dry-run +// query 不带 env 键(交服务端按应用形态自动选分支)。 +func TestAppsDBQuotaGet_DryRunOmitsEnvWhenUnset(t *testing.T) { + factory, stdout, _ := newAppsExecuteFactory(t) + if err := runAppsShortcut(t, AppsDBQuotaGet, + []string{"+db-quota-get", "--app-id", "app_x", "--dry-run", "--as", "user"}, factory, stdout); err != nil { + t.Fatalf("dry-run err=%v", err) + } + var env struct { + API []struct { + Method string `json:"method"` + URL string `json:"url"` + Params map[string]interface{} `json:"params"` + } `json:"api"` + } + _ = json.Unmarshal([]byte(stdout.String()), &env) + a := env.API[0] + if a.Method != "GET" || a.URL != dbQuotaURL { + t.Fatalf("dry-run = %s %s", a.Method, a.URL) + } + if _, ok := a.Params["env"]; ok { + t.Fatalf("no --environment → env key must be omitted, got params=%v", a.Params) + } +} + func TestAppsDBQuotaGet_NoQuotaOmitsFields(t *testing.T) { factory, stdout, reg := newAppsExecuteFactory(t) reg.Register(&httpmock.Stub{ diff --git a/shortcuts/apps/apps_db_table_list_test.go b/shortcuts/apps/apps_db_table_list_test.go index 85e1dd4c1..9cdc12b43 100644 --- a/shortcuts/apps/apps_db_table_list_test.go +++ b/shortcuts/apps/apps_db_table_list_test.go @@ -236,7 +236,11 @@ func TestNumericAsFloat_AllTypes(t *testing.T) { {"json.Number valid", json.Number("13.5"), 13.5, true}, {"json.Number invalid", json.Number("abc"), 0, false}, {"nil", nil, 0, false}, - {"unsupported string", "x", 0, false}, + {"non-numeric string", "x", 0, false}, + {"numeric string", "13.5", 13.5, true}, + {"numeric string int", "2", 2, true}, + {"numeric string padded", " 13.5 ", 13.5, true}, + {"empty string", "", 0, false}, } for _, c := range cases { t.Run(c.name, func(t *testing.T) {