Merge remote-tracking branch 'origin/main' into fix/issue18-reserved-flags

This commit is contained in:
max
2026-09-10 10:32:19 +08:00
9 changed files with 359 additions and 39 deletions
+65 -14
View File
@@ -10,20 +10,22 @@ import (
)
func TestExitCodeMapping(t *testing.T) {
// want 直接寫 README「輸出與結束碼」的數值(0/2/3;內部錯誤 1),
// 不以常數互比,避免常數與規格再次脫鉤(#10)。
cases := []struct {
name string
err error
want ExitCode
want int
}{
{"usage error", &ErrUsage{Msg: "bad flag"}, ExitUsage},
{"api error 401", &gitea.ErrAPI{StatusCode: 401, Op: "GET /api/v1/user"}, ExitAPI},
{"api error transport", &gitea.ErrAPI{Op: "GET /api/v1/user", Err: errString("dial tcp")}, ExitAPI},
{"wrapped api error", wrapped(&gitea.ErrAPI{StatusCode: 500}), ExitAPI},
{"other error", errString("boom"), ExitInternal},
{"nil maps to OK", nil, ExitOK},
{"usage error", &ErrUsage{Msg: "bad flag"}, 2},
{"api error 401", &gitea.ErrAPI{StatusCode: 401, Op: "GET /api/v1/user"}, 3},
{"api error transport", &gitea.ErrAPI{Op: "GET /api/v1/user", Err: errString("dial tcp")}, 3},
{"wrapped api error", wrapped(&gitea.ErrAPI{StatusCode: 500}), 3},
{"other error", errString("boom"), 1},
{"nil maps to OK", nil, 0},
}
for _, tc := range cases {
if got := exitCodeFor(tc.err); got != tc.want {
if got := int(exitCodeFor(tc.err)); got != tc.want {
t.Errorf("%s: exitCodeFor = %d, want %d", tc.name, got, tc.want)
}
}
@@ -68,9 +70,9 @@ func TestRunExitCodes(t *testing.T) {
})
}
func TestParseGlobals(t *testing.T) {
func TestExtractGlobals(t *testing.T) {
g := defaultGlobals()
rest, err := parseGlobals(&g, []string{
rest, err := extractGlobals(&g, []string{
"--url", "https://example.com",
"--token=tok",
"--config", "/tmp/c.yml",
@@ -95,16 +97,65 @@ func TestParseGlobals(t *testing.T) {
}
}
func TestParseGlobalsStopsAtCommand(t *testing.T) {
func TestExtractGlobalsAfterCommand(t *testing.T) {
// 全域選項出現在命令之後也應抽出(README:teai next --output table)。
g := defaultGlobals()
rest, err := parseGlobals(&g, []string{"version", "--output", "table"})
rest, err := extractGlobals(&g, []string{"version", "--output", "table"})
if err != nil {
t.Fatal(err)
}
// 命令之後的選項屬於命令,不屬於全域。
if len(rest) != 3 || rest[0] != "version" {
if len(rest) != 1 || rest[0] != "version" {
t.Fatalf("rest = %v, want [version]", rest)
}
if g.Output != gitea.FormatTable {
t.Fatalf("output = %v, want table", g.Output)
}
}
func TestExtractGlobalsKeepsCommandFlags(t *testing.T) {
// 非全域選項屬於子命令:原樣依序交回,不能攔成 ErrUsage。
cases := [][]string{
{"members", "--has-work"},
{"pulls", "--mine"},
{"pulls", "--reviewer"},
{"pulls", "--repo", "alterminal/teai"},
{"members", "--has-work", "--output", "table"},
{"pulls", "--mine", "--repo", "alterminal/teai", "--output", "table"},
}
for _, args := range cases {
g := defaultGlobals()
rest, err := extractGlobals(&g, args)
if err != nil {
t.Fatalf("extractGlobals(%v) 不應報錯:%v", args, err)
}
want := args
if strings.HasSuffix(strings.Join(args, " "), "--output table") {
want = args[:len(args)-2]
}
if len(rest) != len(want) {
t.Fatalf("extractGlobals(%v) rest = %v, want %v", args, rest, want)
}
for i := range want {
if rest[i] != want[i] {
t.Fatalf("extractGlobals(%v) rest = %v, want %v", args, rest, want)
}
}
}
}
func TestExtractGlobalsDoubleDashStops(t *testing.T) {
g := defaultGlobals()
rest, err := extractGlobals(&g, []string{"--output", "table", "--", "--url", "x"})
if err != nil {
t.Fatal(err)
}
// -- 之後全部交回,--url 不再視為全域選項。
if len(rest) != 2 || rest[0] != "--url" || rest[1] != "x" {
t.Fatalf("rest = %v", rest)
}
if g.Output != gitea.FormatTable {
t.Fatalf("output = %v, want table", g.Output)
}
}
// TestExtractGlobalsReservedFlags 驗證 #18:與全域同名的命令旗標