760 lines
22 KiB
Go
760 lines
22 KiB
Go
package client
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
"mime"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestAPIError(t *testing.T) {
|
|
err := &APIError{StatusCode: 404, Code: "not_found", Message: "PR not found"}
|
|
if err.Error() != "[not_found] PR not found" {
|
|
t.Fatalf("Error() = %q, want %q", err.Error(), "[not_found] PR not found")
|
|
}
|
|
}
|
|
|
|
func TestSuggestFix(t *testing.T) {
|
|
tests := []struct {
|
|
code int
|
|
want string
|
|
}{
|
|
{401, "请先运行 gitlink-cli auth login 登录"},
|
|
{403, "权限不足,请确认账户权限或联系项目管理员"},
|
|
{404, "资源不存在,请检查 owner/repo/id 是否正确"},
|
|
{422, "参数校验失败,请检查请求参数"},
|
|
{500, ""},
|
|
{0, ""},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(http.StatusText(tt.code), func(t *testing.T) {
|
|
if got := suggestFix(tt.code); got != tt.want {
|
|
t.Fatalf("suggestFix(%d) = %q, want %q", tt.code, got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestClientDoSuccess(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{"ok":true,"data":{"key":"value"}}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
env, err := c.Do("GET", "/api/test", nil, nil)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if !env.OK {
|
|
t.Fatal("expected OK=true")
|
|
}
|
|
}
|
|
|
|
func TestClientDoJSONSuffix(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path != "/api/test.json" {
|
|
t.Fatalf("expected path /api/test.json, got %s", r.URL.Path)
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
_, err := c.Do("GET", "/api/test", nil, nil)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestClientDoJSONSuffixPreserved(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path != "/api/test.json" {
|
|
t.Fatalf("expected path /api/test.json, got %s", r.URL.Path)
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
_, err := c.Do("GET", "/api/test.json", nil, nil)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestClientDoQueryParams(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Query().Get("state") != "open" {
|
|
t.Fatalf("expected state=open, got %s", r.URL.Query().Get("state"))
|
|
}
|
|
if r.URL.Query().Get("page") != "1" {
|
|
t.Fatalf("expected page=1, got %s", r.URL.Query().Get("page"))
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
q := url.Values{}
|
|
q.Set("state", "open")
|
|
q.Set("page", "1")
|
|
_, err := c.Do("GET", "/api/test", nil, q)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestClientDoHTTPError(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
w.Write([]byte("not found"))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
_, err := c.Do("GET", "/api/test", nil, nil)
|
|
if err == nil {
|
|
t.Fatal("expected error for 404")
|
|
}
|
|
apiErr, ok := err.(*APIError)
|
|
if !ok {
|
|
t.Fatalf("expected *APIError, got %T", err)
|
|
}
|
|
if apiErr.StatusCode != 404 {
|
|
t.Fatalf("StatusCode = %d, want 404", apiErr.StatusCode)
|
|
}
|
|
}
|
|
|
|
func TestClientDoNonJSON(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Write([]byte("plain text response"))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
env, err := c.Do("GET", "/api/test", nil, nil)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if !env.OK {
|
|
t.Fatal("expected OK=true for non-JSON response")
|
|
}
|
|
}
|
|
|
|
func TestClientDoStatusError(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{"status":403,"message":"Forbidden"}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
env, err := c.Do("GET", "/api/test", nil, nil)
|
|
if err == nil {
|
|
t.Fatal("expected error for status=403")
|
|
}
|
|
if env == nil {
|
|
t.Fatal("expected envelope for status error")
|
|
}
|
|
if env.OK {
|
|
t.Fatal("expected OK=false for status error")
|
|
}
|
|
}
|
|
|
|
func TestClientDoGatewayCodeError(t *testing.T) {
|
|
// Gateway returns {"code":N, "msg":"..."} instead of {"status":N, "message":"..."}
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{"code":400,"msg":"Bad Request"}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
env, err := c.Do("GET", "/api/test", nil, nil)
|
|
if err == nil {
|
|
t.Fatal("expected error for code=400")
|
|
}
|
|
if env == nil {
|
|
t.Fatal("expected envelope for code error")
|
|
}
|
|
if env.OK {
|
|
t.Fatal("expected OK=false for code=400")
|
|
}
|
|
}
|
|
|
|
func TestClientDoGatewayCode201Success(t *testing.T) {
|
|
// Gateway returns code=201 with JSON string data — should be treated as success
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{"code":201,"msg":"","data":"{\"title\":\"test\"}"}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
env, err := c.Do("POST", "/api/test", map[string]string{"title": "test"}, nil)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error for code=201: %v", err)
|
|
}
|
|
if !env.OK {
|
|
t.Fatal("expected OK=true for code=201")
|
|
}
|
|
}
|
|
|
|
func TestClientDoStatusZero(t *testing.T) {
|
|
// status=0, 200, 1 are treated as success
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{"status":0,"data":"ok"}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
env, err := c.Do("GET", "/api/test", nil, nil)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if !env.OK {
|
|
t.Fatal("expected OK=true for status=0")
|
|
}
|
|
}
|
|
|
|
func TestClientDoPaginationMeta(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{"total_count":100,"page":1,"limit":20,"data":[]}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
env, err := c.Do("GET", "/api/test", nil, nil)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if env.Meta == nil {
|
|
t.Fatal("expected Meta to be populated")
|
|
}
|
|
if env.Meta.TotalCount != 100 {
|
|
t.Fatalf("TotalCount = %d, want 100", env.Meta.TotalCount)
|
|
}
|
|
if env.Meta.Page != 1 {
|
|
t.Fatalf("Page = %d, want 1", env.Meta.Page)
|
|
}
|
|
if env.Meta.Limit != 20 {
|
|
t.Fatalf("Limit = %d, want 20", env.Meta.Limit)
|
|
}
|
|
}
|
|
|
|
func TestClientDoPathWithQuery(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
// The path query param should be preserved
|
|
if r.URL.Query().Get("filepath") != "test.go" {
|
|
t.Fatalf("expected filepath=test.go, got %s", r.URL.Query().Get("filepath"))
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
_, err := c.Do("GET", "/api/sub_entries?filepath=test.go", nil, nil)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestClientDoPathWithQueryAndExtraParams(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Query().Get("ref") != "master" {
|
|
t.Fatalf("expected ref=master, got %s", r.URL.Query().Get("ref"))
|
|
}
|
|
if r.URL.Query().Get("filepath") != "test.go" {
|
|
t.Fatalf("expected filepath=test.go, got %s", r.URL.Query().Get("filepath"))
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
q := url.Values{}
|
|
q.Set("ref", "master")
|
|
_, err := c.Do("GET", "/api/sub_entries?filepath=test.go", nil, q)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestClientDoWithBody(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != "POST" {
|
|
t.Fatalf("expected POST, got %s", r.Method)
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{"id":123}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
env, err := c.Do("POST", "/api/create", map[string]string{"title": "test"}, nil)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if !env.OK {
|
|
t.Fatal("expected OK=true")
|
|
}
|
|
}
|
|
|
|
func TestClientPostMultipart(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
t.Fatalf("expected POST, got %s", r.Method)
|
|
}
|
|
if r.URL.Path != "/api/attachments.json" {
|
|
t.Fatalf("expected path /api/attachments.json, got %s", r.URL.Path)
|
|
}
|
|
|
|
mediaType, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
|
if err != nil {
|
|
t.Fatalf("parse media type: %v", err)
|
|
}
|
|
if mediaType != "multipart/form-data" {
|
|
t.Fatalf("Content-Type = %q, want multipart/form-data", mediaType)
|
|
}
|
|
|
|
if err := r.ParseMultipartForm(1 << 20); err != nil {
|
|
t.Fatalf("ParseMultipartForm: %v", err)
|
|
}
|
|
if got := r.FormValue("description"); got != "release asset" {
|
|
t.Fatalf("description = %q, want %q", got, "release asset")
|
|
}
|
|
|
|
files := r.MultipartForm.File["file"]
|
|
if len(files) != 1 {
|
|
t.Fatalf("expected 1 uploaded file, got %d", len(files))
|
|
}
|
|
if files[0].Filename != "asset.zip" {
|
|
t.Fatalf("filename = %q, want %q", files[0].Filename, "asset.zip")
|
|
}
|
|
if got := files[0].Header.Get("Content-Type"); got != "application/octet-stream" {
|
|
t.Fatalf("part Content-Type = %q, want %q", got, "application/octet-stream")
|
|
}
|
|
|
|
file, err := files[0].Open()
|
|
if err != nil {
|
|
t.Fatalf("open multipart file: %v", err)
|
|
}
|
|
defer file.Close()
|
|
|
|
data, err := io.ReadAll(file)
|
|
if err != nil {
|
|
t.Fatalf("read multipart file: %v", err)
|
|
}
|
|
if string(data) != "binary content" {
|
|
t.Fatalf("file body = %q, want %q", string(data), "binary content")
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{"id":"asset-1"}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
env, err := c.PostMultipart("/api/attachments", map[string]string{
|
|
"description": "release asset",
|
|
}, []MultipartFile{
|
|
{
|
|
FieldName: "file",
|
|
FileName: "asset.zip",
|
|
ContentType: "application/octet-stream",
|
|
Reader: strings.NewReader("binary content"),
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if !env.OK {
|
|
t.Fatal("expected OK=true")
|
|
}
|
|
}
|
|
|
|
func TestClientPostMultipartRequiresFile(t *testing.T) {
|
|
c := &Client{HTTP: &http.Client{}, BaseURL: "https://gitlink.example.com"}
|
|
_, err := c.PostMultipart("/attachments", nil, nil)
|
|
if err == nil {
|
|
t.Fatal("expected error when no multipart file is provided")
|
|
}
|
|
}
|
|
|
|
func TestClientGet(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != "GET" {
|
|
t.Fatalf("expected GET, got %s", r.Method)
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
_, err := c.Get("/api/test", nil)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestClientPost(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != "POST" {
|
|
t.Fatalf("expected POST, got %s", r.Method)
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
_, err := c.Post("/api/test", nil)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestClientPut(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != "PUT" {
|
|
t.Fatalf("expected PUT, got %s", r.Method)
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
_, err := c.Put("/api/test", nil)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestClientDelete(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != "DELETE" {
|
|
t.Fatalf("expected DELETE, got %s", r.Method)
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
_, err := c.Delete("/api/test", nil)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestClientDoInvalidURL(t *testing.T) {
|
|
c := &Client{HTTP: &http.Client{}, BaseURL: "://invalid"}
|
|
_, err := c.Do("GET", "/api/test", nil, nil)
|
|
if err == nil {
|
|
t.Fatal("expected error for invalid URL")
|
|
}
|
|
}
|
|
|
|
func TestClientDebug(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL, Debug: true}
|
|
_, err := c.Do("GET", "/api/test", nil, nil)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestClientDoStatusInt(t *testing.T) {
|
|
// Some APIs return status as int, not float64
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{"status":404,"message":"Not Found"}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
_, err := c.Do("GET", "/api/test", nil, nil)
|
|
if err == nil {
|
|
t.Fatal("expected error for status=404 (int)")
|
|
}
|
|
}
|
|
|
|
func TestClientNew(t *testing.T) {
|
|
dir := t.TempDir()
|
|
t.Setenv("GITLINK_CONFIG_DIR", dir)
|
|
cfgPath := filepath.Join(dir, "config.yaml")
|
|
os.WriteFile(cfgPath, []byte("base_url: https://gitlink.example.com/api/v1\n"), 0644)
|
|
|
|
cli, err := New()
|
|
if err != nil {
|
|
t.Fatalf("New error: %v", err)
|
|
}
|
|
if cli.BaseURL != "https://gitlink.example.com/api/v1" {
|
|
t.Fatalf("BaseURL = %q", cli.BaseURL)
|
|
}
|
|
if cli.HTTP == nil {
|
|
t.Fatal("HTTP client is nil")
|
|
}
|
|
}
|
|
|
|
func TestPaginateAllSinglePage(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{"data":[{"id":1},{"id":2}]}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
items, err := c.PaginateAll("/test", nil)
|
|
if err != nil {
|
|
t.Fatalf("PaginateAll error: %v", err)
|
|
}
|
|
if len(items) != 2 {
|
|
t.Fatalf("expected 2 items, got %d", len(items))
|
|
}
|
|
}
|
|
|
|
func TestPaginateAllMultiPage(t *testing.T) {
|
|
callCount := 0
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
callCount++
|
|
w.Header().Set("Content-Type", "application/json")
|
|
page := r.URL.Query().Get("page")
|
|
if page == "1" {
|
|
w.Write([]byte(`{"data":[{"id":1},{"id":2}]}`))
|
|
} else {
|
|
w.Write([]byte(`{"data":[{"id":3}]}`))
|
|
}
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
params := url.Values{}
|
|
params.Set("limit", "2")
|
|
items, err := c.PaginateAll("/test", params)
|
|
if err != nil {
|
|
t.Fatalf("PaginateAll error: %v", err)
|
|
}
|
|
if len(items) != 3 {
|
|
t.Fatalf("expected 3 items, got %d", len(items))
|
|
}
|
|
if callCount != 2 {
|
|
t.Fatalf("expected 2 API calls, got %d", callCount)
|
|
}
|
|
}
|
|
|
|
func TestPaginateAllWrappedData(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{"data":[{"id":1},{"id":2}],"total_count":2}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
items, err := c.PaginateAll("/test", nil)
|
|
if err != nil {
|
|
t.Fatalf("PaginateAll error: %v", err)
|
|
}
|
|
if len(items) != 2 {
|
|
t.Fatalf("expected 2 items, got %d", len(items))
|
|
}
|
|
}
|
|
|
|
func TestPaginateAllSingleObject(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{"name":"single-object"}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
items, err := c.PaginateAll("/test", nil)
|
|
if err != nil {
|
|
t.Fatalf("PaginateAll error: %v", err)
|
|
}
|
|
if len(items) != 1 {
|
|
t.Fatalf("expected 1 item, got %d", len(items))
|
|
}
|
|
var data map[string]interface{}
|
|
json.Unmarshal(items[0], &data)
|
|
if data["name"] != "single-object" {
|
|
t.Fatalf("unexpected data: %v", data)
|
|
}
|
|
}
|
|
|
|
func TestPaginateAllHTTPError(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
_, err := c.PaginateAll("/test", nil)
|
|
if err == nil {
|
|
t.Fatal("expected error for 500 response")
|
|
}
|
|
}
|
|
|
|
func TestPaginateAllNotOK(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{"status":500,"message":"error"}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
_, err := c.PaginateAll("/test", nil)
|
|
if err == nil {
|
|
t.Fatal("expected error when envelope ok=false")
|
|
}
|
|
}
|
|
|
|
func TestClientDownload(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path != "/api/attachments/7" {
|
|
t.Fatalf("unexpected path: %s", r.URL.Path)
|
|
}
|
|
w.Header().Set("Content-Type", "application/octet-stream")
|
|
w.Write([]byte("asset bytes"))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL + "/api"}
|
|
result, err := c.Download("/api/attachments/7")
|
|
if err != nil {
|
|
t.Fatalf("Download error: %v", err)
|
|
}
|
|
if string(result.Data) != "asset bytes" {
|
|
t.Fatalf("data = %q", result.Data)
|
|
}
|
|
if result.ContentType != "application/octet-stream" {
|
|
t.Fatalf("content type = %q", result.ContentType)
|
|
}
|
|
}
|
|
|
|
func TestClientDownloadAPIPathWithV1BaseURL(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path != "/api/attachments/7" {
|
|
t.Fatalf("unexpected path: %s", r.URL.Path)
|
|
}
|
|
w.Write([]byte("asset bytes"))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL + "/api/v1"}
|
|
result, err := c.Download("/api/attachments/7")
|
|
if err != nil {
|
|
t.Fatalf("Download error: %v", err)
|
|
}
|
|
if string(result.Data) != "asset bytes" {
|
|
t.Fatalf("data = %q", result.Data)
|
|
}
|
|
}
|
|
|
|
func TestClientDownloadAbsoluteURL(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path != "/files/release.zip" {
|
|
t.Fatalf("unexpected path: %s", r.URL.Path)
|
|
}
|
|
w.Write([]byte("zip bytes"))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: "https://gitlink.example.com/api"}
|
|
result, err := c.Download(server.URL + "/files/release.zip")
|
|
if err != nil {
|
|
t.Fatalf("Download error: %v", err)
|
|
}
|
|
if string(result.Data) != "zip bytes" {
|
|
t.Fatalf("data = %q", result.Data)
|
|
}
|
|
}
|
|
|
|
func TestClientDownloadWebRelativeURL(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path != "/owner/repo/releases/download/v1/app.zip" {
|
|
t.Fatalf("unexpected path: %s", r.URL.Path)
|
|
}
|
|
w.Write([]byte("asset bytes"))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL + "/api"}
|
|
result, err := c.Download("/owner/repo/releases/download/v1/app.zip")
|
|
if err != nil {
|
|
t.Fatalf("Download error: %v", err)
|
|
}
|
|
if string(result.Data) != "asset bytes" {
|
|
t.Fatalf("data = %q", result.Data)
|
|
}
|
|
}
|
|
|
|
func TestClientDownloadHTTPError(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
w.Write([]byte("missing"))
|
|
}))
|
|
defer server.Close()
|
|
|
|
c := &Client{HTTP: server.Client(), BaseURL: server.URL}
|
|
_, err := c.Download("/missing")
|
|
if err == nil {
|
|
t.Fatal("expected download error")
|
|
}
|
|
}
|
|
|
|
func TestShouldAppendJSONSuffixSkipsRawFilePath(t *testing.T) {
|
|
if shouldAppendJSONSuffix("/Gitlink/forgeplus/raw/master/README.md") {
|
|
t.Fatal("raw file path should not get .json suffix")
|
|
}
|
|
}
|
|
|
|
func TestShouldAppendJSONSuffixKeepsRawRepositoryName(t *testing.T) {
|
|
if !shouldAppendJSONSuffix("/users/raw/projects") {
|
|
t.Fatal("regular API path should get .json suffix")
|
|
}
|
|
}
|
|
|
|
func TestShouldAppendJSONSuffixSkipsExistingJSONPath(t *testing.T) {
|
|
if shouldAppendJSONSuffix("/projects.json") {
|
|
t.Fatal("existing .json path should not get another suffix")
|
|
}
|
|
}
|
|
|
|
func TestShouldAppendJSONSuffixSkipsWikiOpenPaths(t *testing.T) {
|
|
paths := []string{
|
|
"/wiki/open/createWiki",
|
|
"/wiki/open/getWiki",
|
|
"/wiki/open/updateWiki",
|
|
"/wiki/open/deleteWiki",
|
|
"/wiki/open/wikiPages",
|
|
}
|
|
for _, p := range paths {
|
|
if shouldAppendJSONSuffix(p) {
|
|
t.Errorf("wiki/open path %q should not get .json suffix", p)
|
|
}
|
|
}
|
|
}
|