feat: add wiki +view,+create,+update,+delete shortcuts with tests

This commit is contained in:
15972095207 2026-06-02 10:42:25 +08:00
parent 1e28d3775d
commit 0362f3f604
2 changed files with 219 additions and 0 deletions

View File

@ -1,6 +1,7 @@
package wiki
import (
"encoding/base64"
"fmt"
"github.com/gitlink-org/gitlink-cli/shortcuts/common"
@ -23,9 +24,115 @@ func Shortcuts() []*common.Shortcut {
return ctx.Output(env)
},
},
{
Name: "view",
Description: "View a wiki page",
Flags: []common.Flag{
{Name: "slug", Short: "s", Usage: "Wiki page slug", Required: true},
},
Run: func(ctx *common.RuntimeContext) error {
if err := ctx.ResolveOwnerRepo(); err != nil {
return err
}
slug, err := ctx.RequireArg("slug")
if err != nil {
return err
}
env, err := ctx.CallAPI("GET", wikiPagePath(ctx, slug), nil)
if err != nil {
return err
}
return ctx.Output(env)
},
},
{
Name: "create",
Description: "Create a wiki page",
Flags: []common.Flag{
{Name: "title", Short: "t", Usage: "Wiki page title", Required: true},
{Name: "body", Short: "b", Usage: "Wiki page content", Required: true},
},
Run: func(ctx *common.RuntimeContext) error {
if err := ctx.ResolveOwnerRepo(); err != nil {
return err
}
title, err := ctx.RequireArg("title")
if err != nil {
return err
}
body, err := ctx.RequireArg("body")
if err != nil {
return err
}
payload := map[string]interface{}{
"title": title,
"content_base64": base64.StdEncoding.EncodeToString([]byte(body)),
}
env, err := ctx.CallAPI("POST", wikiPagesPath(ctx), payload)
if err != nil {
return err
}
return ctx.Output(env)
},
},
{
Name: "update",
Description: "Update a wiki page",
Flags: []common.Flag{
{Name: "slug", Short: "s", Usage: "Wiki page slug", Required: true},
{Name: "title", Short: "t", Usage: "New title"},
{Name: "body", Short: "b", Usage: "New content"},
},
Run: func(ctx *common.RuntimeContext) error {
if err := ctx.ResolveOwnerRepo(); err != nil {
return err
}
slug, err := ctx.RequireArg("slug")
if err != nil {
return err
}
payload := map[string]interface{}{}
if title := ctx.Arg("title"); title != "" {
payload["title"] = title
}
if body := ctx.Arg("body"); body != "" {
payload["content_base64"] = base64.StdEncoding.EncodeToString([]byte(body))
}
env, err := ctx.CallAPI("PATCH", wikiPagePath(ctx, slug), payload)
if err != nil {
return err
}
return ctx.Output(env)
},
},
{
Name: "delete",
Description: "Delete a wiki page",
Flags: []common.Flag{
{Name: "slug", Short: "s", Usage: "Wiki page slug", Required: true},
},
Run: func(ctx *common.RuntimeContext) error {
if err := ctx.ResolveOwnerRepo(); err != nil {
return err
}
slug, err := ctx.RequireArg("slug")
if err != nil {
return err
}
env, err := ctx.CallAPI("DELETE", wikiPagePath(ctx, slug), nil)
if err != nil {
return err
}
return ctx.Output(env)
},
},
}
}
func wikiPagesPath(ctx *common.RuntimeContext) string {
return fmt.Sprintf("/%s/%s/wiki/pages", ctx.Owner, ctx.Repo)
}
func wikiPagePath(ctx *common.RuntimeContext, slug string) string {
return fmt.Sprintf("/%s/%s/wiki/pages/%s", ctx.Owner, ctx.Repo, slug)
}

View File

@ -1,6 +1,7 @@
package wiki
import (
"encoding/base64"
"encoding/json"
"net/http"
"net/http/httptest"
@ -10,6 +11,8 @@ import (
"github.com/gitlink-org/gitlink-cli/shortcuts/common"
)
// --- List ---
func TestWikiList(t *testing.T) {
server := newWikiTestServer(t, func(w http.ResponseWriter, r *http.Request) {
assertRequest(t, r, "GET", "/owner/repo/wiki/pages.json")
@ -28,6 +31,99 @@ func TestWikiList(t *testing.T) {
}
}
// --- View ---
func TestWikiView(t *testing.T) {
server := newWikiTestServer(t, func(w http.ResponseWriter, r *http.Request) {
assertRequest(t, r, "GET", "/owner/repo/wiki/pages/home.json")
writeJSON(t, w, map[string]interface{}{
"title": "Home",
"slug": "home",
"content_base64": base64.StdEncoding.EncodeToString([]byte("Welcome to the wiki")),
})
})
defer server.Close()
if err := runWikiShortcut(t, server, "view", map[string]string{"slug": "home"}); err != nil {
t.Fatalf("view shortcut failed: %v", err)
}
}
// --- Create ---
func TestWikiCreate(t *testing.T) {
server := newWikiTestServer(t, func(w http.ResponseWriter, r *http.Request) {
assertRequest(t, r, "POST", "/owner/repo/wiki/pages.json")
body := decodeJSON(t, r)
assertEqual(t, body["title"], "TestPage")
decoded, err := base64.StdEncoding.DecodeString(body["content_base64"].(string))
if err != nil {
t.Fatalf("failed to decode content_base64: %v", err)
}
assertEqual(t, string(decoded), "Hello World")
writeJSON(t, w, map[string]interface{}{
"title": "TestPage",
"slug": "TestPage",
})
})
defer server.Close()
if err := runWikiShortcut(t, server, "create", map[string]string{
"title": "TestPage",
"body": "Hello World",
}); err != nil {
t.Fatalf("create shortcut failed: %v", err)
}
}
// --- Update ---
func TestWikiUpdate(t *testing.T) {
server := newWikiTestServer(t, func(w http.ResponseWriter, r *http.Request) {
assertRequest(t, r, "PATCH", "/owner/repo/wiki/pages/home.json")
body := decodeJSON(t, r)
assertEqual(t, body["title"], "Updated Title")
decoded, err := base64.StdEncoding.DecodeString(body["content_base64"].(string))
if err != nil {
t.Fatalf("failed to decode content_base64: %v", err)
}
assertEqual(t, string(decoded), "Updated content")
writeJSON(t, w, map[string]interface{}{
"title": "Updated Title",
"slug": "home",
})
})
defer server.Close()
if err := runWikiShortcut(t, server, "update", map[string]string{
"slug": "home",
"title": "Updated Title",
"body": "Updated content",
}); err != nil {
t.Fatalf("update shortcut failed: %v", err)
}
}
// --- Delete ---
func TestWikiDelete(t *testing.T) {
server := newWikiTestServer(t, func(w http.ResponseWriter, r *http.Request) {
assertRequest(t, r, "DELETE", "/owner/repo/wiki/pages/old-page.json")
writeJSON(t, w, map[string]interface{}{
"message": "deleted",
})
})
defer server.Close()
if err := runWikiShortcut(t, server, "delete", map[string]string{
"slug": "old-page",
}); err != nil {
t.Fatalf("delete shortcut failed: %v", err)
}
}
// --- test helpers ---
func runWikiShortcut(t *testing.T, server *httptest.Server, name string, args map[string]string) error {
@ -79,3 +175,19 @@ func writeJSON(t *testing.T, w http.ResponseWriter, payload interface{}) {
t.Fatalf("failed to write response: %v", err)
}
}
func decodeJSON(t *testing.T, r *http.Request) map[string]interface{} {
t.Helper()
var m map[string]interface{}
if err := json.NewDecoder(r.Body).Decode(&m); err != nil {
t.Fatalf("failed to decode request body: %v", err)
}
return m
}
func assertEqual(t *testing.T, got, want interface{}) {
t.Helper()
if got != want {
t.Fatalf("got %v, want %v", got, want)
}
}