internal/gitea:API 用戶端、認證與輸出基礎(#5)
- internal/gitea:僅標準庫的 HTTP 用戶端;ListAll 以 limit=50 逐頁抓滿 - 認證選序 --token → TEAI_TOKEN → tea 組態(--config/TEA_CONFIG/預設路徑); token 不入輸出、日誌與錯誤訊息 - 共用輸出 --output json|table(預設 json)、--timeout(預設 30s) - CLI 結束碼 0/2/3:用法錯誤 → 2、API 錯誤(*gitea.ErrAPI)→ 3 - 單元測試:認證選序、tea 組態解析、分頁、逾時/401/5xx 錯誤映射、輸出 實作 issue #5
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
// output_test.go 驗證共用輸出:JSON 物件順序、空清單、table 對齊與
|
||||
// 格式解析。
|
||||
package gitea
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var demoFields = []Field{
|
||||
{Name: "type"},
|
||||
{Name: "number"},
|
||||
}
|
||||
|
||||
func TestPrintListJSON(t *testing.T) {
|
||||
var b bytes.Buffer
|
||||
p := Printer{Format: FormatJSON, Out: &b}
|
||||
err := p.PrintList(demoFields, []Values{{"issue", 5}, {"pull", 7}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var got []map[string]any
|
||||
if err := json.Unmarshal(b.Bytes(), &got); err != nil {
|
||||
t.Fatalf("invalid JSON %q: %v", b.String(), err)
|
||||
}
|
||||
if len(got) != 2 || got[0]["type"] != "issue" || got[1]["number"] != float64(7) {
|
||||
t.Fatalf("unexpected payload: %v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrintListEmptyJSONArray(t *testing.T) {
|
||||
var b bytes.Buffer
|
||||
p := Printer{Format: FormatJSON, Out: &b}
|
||||
if err := p.PrintList(demoFields, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if strings.TrimSpace(b.String()) != "[]" {
|
||||
t.Fatalf("want [], got %q", b.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrintNull(t *testing.T) {
|
||||
var b bytes.Buffer
|
||||
p := Printer{Format: FormatJSON, Out: &b}
|
||||
if err := p.PrintNull(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if strings.TrimSpace(b.String()) != "null" {
|
||||
t.Fatalf("want null, got %q", b.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrintTable(t *testing.T) {
|
||||
var b bytes.Buffer
|
||||
p := Printer{Format: FormatTable, Out: &b}
|
||||
if err := p.PrintList(demoFields, []Values{{"issue", 5}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
out := b.String()
|
||||
for _, want := range []string{"type", "number", "issue", "5"} {
|
||||
if !strings.Contains(out, want) {
|
||||
t.Fatalf("table missing %q:\n%s", want, out)
|
||||
}
|
||||
}
|
||||
if !strings.Contains(out, "─") {
|
||||
t.Fatalf("table should have separator:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseFormat(t *testing.T) {
|
||||
for in, want := range map[string]Format{
|
||||
"": FormatJSON,
|
||||
"json": FormatJSON,
|
||||
"JSON": FormatJSON,
|
||||
"table": FormatTable,
|
||||
" Table ": FormatTable,
|
||||
} {
|
||||
got, err := ParseFormat(in)
|
||||
if err != nil || got != want {
|
||||
t.Errorf("ParseFormat(%q) = %v, %v; want %v", in, got, err, want)
|
||||
}
|
||||
}
|
||||
if _, err := ParseFormat("yaml"); err == nil {
|
||||
t.Error("yaml should be rejected")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user