forked from Gitlink/gitlink-cli
221 lines
6.5 KiB
Go
221 lines
6.5 KiB
Go
package repo
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/gitlink-org/gitlink-cli/internal/client"
|
|
"github.com/gitlink-org/gitlink-cli/shortcuts/common"
|
|
)
|
|
|
|
func runBatchDeleteShortcut(t *testing.T, server *httptest.Server, owner string, args map[string]string) error {
|
|
t.Helper()
|
|
s := findShortcut(t, "batch-delete")
|
|
ctx := &common.RuntimeContext{
|
|
Client: &client.Client{HTTP: server.Client(), BaseURL: server.URL},
|
|
Owner: owner,
|
|
Format: "json",
|
|
Args: args,
|
|
}
|
|
return s.Run(ctx)
|
|
}
|
|
|
|
func TestBatchDelete_DryRun(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
t.Fatalf("no API calls expected in dry-run mode, got %s %s", r.Method, r.URL.Path)
|
|
}))
|
|
defer server.Close()
|
|
|
|
err := runBatchDeleteShortcut(t, server, "testuser", map[string]string{
|
|
"names": "repo1,repo2",
|
|
"dry-run": "true",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestBatchDelete_FromNames(t *testing.T) {
|
|
var deletedPaths []string
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != "DELETE" {
|
|
t.Fatalf("expected DELETE, got %s", r.Method)
|
|
}
|
|
deletedPaths = append(deletedPaths, r.URL.Path)
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte(`{"ok":true}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
err := runBatchDeleteShortcut(t, server, "zzx-coder", map[string]string{
|
|
"names": "test-batch-1,test-batch-2,test-batch-3",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if len(deletedPaths) != 3 {
|
|
t.Fatalf("expected 3 DELETE calls, got %d", len(deletedPaths))
|
|
}
|
|
expected := []string{"/zzx-coder/test-batch-1.json", "/zzx-coder/test-batch-2.json", "/zzx-coder/test-batch-3.json"}
|
|
for i, p := range deletedPaths {
|
|
if p != expected[i] {
|
|
t.Fatalf("path[%d]: got %q, want %q", i, p, expected[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestBatchDelete_NoNames(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
t.Fatalf("unexpected request: %s %s", r.Method, r.URL.Path)
|
|
}))
|
|
defer server.Close()
|
|
|
|
err := runBatchDeleteShortcut(t, server, "zzx-coder", map[string]string{})
|
|
if err == nil {
|
|
t.Fatal("expected error, got nil")
|
|
}
|
|
if !strings.Contains(err.Error(), "no repository names provided") {
|
|
t.Fatalf("error should mention no names, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestBatchDelete_NoOwner(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
t.Fatalf("unexpected request: %s %s", r.Method, r.URL.Path)
|
|
}))
|
|
defer server.Close()
|
|
|
|
err := runBatchDeleteShortcut(t, server, "", map[string]string{
|
|
"names": "repo1,repo2",
|
|
})
|
|
if err == nil {
|
|
t.Fatal("expected error, got nil")
|
|
}
|
|
if !strings.Contains(err.Error(), "--owner is required") {
|
|
t.Fatalf("error should mention --owner required, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestBatchDelete_DryRunNoNamesErrors(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
t.Fatalf("unexpected request: %s %s", r.Method, r.URL.Path)
|
|
}))
|
|
defer server.Close()
|
|
|
|
err := runBatchDeleteShortcut(t, server, "zzx-coder", map[string]string{"dry-run": "true"})
|
|
if err == nil {
|
|
t.Fatal("expected error for no names even in dry-run, got nil")
|
|
}
|
|
}
|
|
|
|
func TestBatchDelete_FromCSV(t *testing.T) {
|
|
csvPath := writeTempCSV(t, "name\ncsv-repo1\ncsv-repo2\n")
|
|
|
|
var deletedPaths []string
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != "DELETE" {
|
|
t.Fatalf("expected DELETE, got %s", r.Method)
|
|
}
|
|
deletedPaths = append(deletedPaths, r.URL.Path)
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte(`{"ok":true}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
err := runBatchDeleteShortcut(t, server, "zzx-coder", map[string]string{"from": csvPath})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if len(deletedPaths) != 2 {
|
|
t.Fatalf("expected 2 DELETE calls, got %d", len(deletedPaths))
|
|
}
|
|
if deletedPaths[0] != "/zzx-coder/csv-repo1.json" {
|
|
t.Fatalf("first path: got %q", deletedPaths[0])
|
|
}
|
|
if deletedPaths[1] != "/zzx-coder/csv-repo2.json" {
|
|
t.Fatalf("second path: got %q", deletedPaths[1])
|
|
}
|
|
}
|
|
|
|
func TestBatchDelete_CSVAndNamesCombined(t *testing.T) {
|
|
csvPath := writeTempCSV(t, "name\ncsv-repo\n")
|
|
|
|
var deletedPaths []string
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
deletedPaths = append(deletedPaths, r.URL.Path)
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte(`{"ok":true}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
err := runBatchDeleteShortcut(t, server, "zzx-coder", map[string]string{
|
|
"names": "inline-repo",
|
|
"from": csvPath,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if len(deletedPaths) != 2 {
|
|
t.Fatalf("expected 2 deletes (inline + csv), got %d", len(deletedPaths))
|
|
}
|
|
if deletedPaths[0] != "/zzx-coder/inline-repo.json" {
|
|
t.Fatalf("first: got %q", deletedPaths[0])
|
|
}
|
|
if deletedPaths[1] != "/zzx-coder/csv-repo.json" {
|
|
t.Fatalf("second: got %q", deletedPaths[1])
|
|
}
|
|
}
|
|
|
|
func TestBatchDelete_PartialFailure(t *testing.T) {
|
|
callCount := 0
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
callCount++
|
|
if callCount == 2 {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
w.Write([]byte(`{"message":"repo not found"}`))
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte(`{"ok":true}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
err := runBatchDeleteShortcut(t, server, "zzx-coder", map[string]string{
|
|
"names": "ok1,fail1,ok2",
|
|
})
|
|
if err == nil {
|
|
t.Fatal("expected error from partial failure, got nil")
|
|
}
|
|
if !strings.Contains(err.Error(), "failed to delete") {
|
|
t.Fatalf("error should mention failed count, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestBatchDelete_TrimsWhitespace(t *testing.T) {
|
|
var deletedPaths []string
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
deletedPaths = append(deletedPaths, r.URL.Path)
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte(`{"ok":true}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
err := runBatchDeleteShortcut(t, server, "zzx-coder", map[string]string{
|
|
"names": " repo-a , repo-b ,",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if len(deletedPaths) != 2 {
|
|
t.Fatalf("expected 2 deletes after trimming, got %d", len(deletedPaths))
|
|
}
|
|
if deletedPaths[0] != "/zzx-coder/repo-a.json" {
|
|
t.Fatalf("first: got %q", deletedPaths[0])
|
|
}
|
|
if deletedPaths[1] != "/zzx-coder/repo-b.json" {
|
|
t.Fatalf("second: got %q", deletedPaths[1])
|
|
}
|
|
}
|