gogcli/internal/cmd/execute_export_cmds_test.go
2025-12-31 17:38:29 +01:00

267 lines
7.4 KiB
Go

package cmd
import (
"context"
"encoding/json"
"errors"
"io"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"testing"
"google.golang.org/api/drive/v3"
"google.golang.org/api/option"
)
func TestExecute_SheetsExport_DefaultXLSX(t *testing.T) {
origNew := newDriveService
origExport := driveExportDownload
t.Cleanup(func() {
newDriveService = origNew
driveExportDownload = origExport
})
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.NotFound(w, r)
return
}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{
"id": "sheet1",
"name": "My Sheet",
"mimeType": "application/vnd.google-apps.spreadsheet",
})
}))
defer srv.Close()
svc, err := drive.NewService(context.Background(),
option.WithoutAuthentication(),
option.WithHTTPClient(srv.Client()),
option.WithEndpoint(srv.URL+"/"),
)
if err != nil {
t.Fatalf("NewService: %v", err)
}
newDriveService = func(context.Context, string) (*drive.Service, error) { return svc, nil }
var gotMime string
driveExportDownload = func(_ context.Context, _ *drive.Service, fileID string, mimeType string) (*http.Response, error) {
gotMime = mimeType
return &http.Response{
Status: "200 OK",
StatusCode: http.StatusOK,
Body: io.NopCloser(strings.NewReader("XLSX-FAKE")),
}, nil
}
dest := filepath.Join(t.TempDir(), "out")
out := captureStdout(t, func() {
_ = captureStderr(t, func() {
if err := Execute([]string{"--json", "--account", "a@b.com", "sheets", "export", "sheet1", "--out", dest}); err != nil {
t.Fatalf("Execute: %v", err)
}
})
})
if gotMime != "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" {
t.Fatalf("mimeType=%q", gotMime)
}
var parsed struct {
Path string `json:"path"`
Size int64 `json:"size"`
}
if err := json.Unmarshal([]byte(out), &parsed); err != nil {
t.Fatalf("json parse: %v\nout=%q", err, out)
}
if !strings.HasSuffix(parsed.Path, ".xlsx") {
t.Fatalf("expected .xlsx path, got %q", parsed.Path)
}
if b, err := os.ReadFile(parsed.Path); err != nil || string(b) != "XLSX-FAKE" {
t.Fatalf("file mismatch: err=%v body=%q", err, string(b))
}
}
func TestExecute_DocsExport_DOCX(t *testing.T) {
origNew := newDriveService
origExport := driveExportDownload
t.Cleanup(func() {
newDriveService = origNew
driveExportDownload = origExport
})
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.NotFound(w, r)
return
}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{
"id": "doc1",
"name": "My Doc",
"mimeType": "application/vnd.google-apps.document",
})
}))
defer srv.Close()
svc, err := drive.NewService(context.Background(),
option.WithoutAuthentication(),
option.WithHTTPClient(srv.Client()),
option.WithEndpoint(srv.URL+"/"),
)
if err != nil {
t.Fatalf("NewService: %v", err)
}
newDriveService = func(context.Context, string) (*drive.Service, error) { return svc, nil }
var gotMime string
driveExportDownload = func(_ context.Context, _ *drive.Service, fileID string, mimeType string) (*http.Response, error) {
gotMime = mimeType
return &http.Response{
Status: "200 OK",
StatusCode: http.StatusOK,
Body: io.NopCloser(strings.NewReader("DOCX-FAKE")),
}, nil
}
dest := filepath.Join(t.TempDir(), "out")
out := captureStdout(t, func() {
_ = captureStderr(t, func() {
if err := Execute([]string{"--json", "--account", "a@b.com", "docs", "export", "doc1", "--format", "docx", "--out", dest}); err != nil {
t.Fatalf("Execute: %v", err)
}
})
})
if gotMime != "application/vnd.openxmlformats-officedocument.wordprocessingml.document" {
t.Fatalf("mimeType=%q", gotMime)
}
var parsed struct {
Path string `json:"path"`
}
if err := json.Unmarshal([]byte(out), &parsed); err != nil {
t.Fatalf("json parse: %v\nout=%q", err, out)
}
if !strings.HasSuffix(parsed.Path, ".docx") {
t.Fatalf("expected .docx path, got %q", parsed.Path)
}
}
func TestExecute_SlidesExport_DefaultPPTX(t *testing.T) {
origNew := newDriveService
origExport := driveExportDownload
t.Cleanup(func() {
newDriveService = origNew
driveExportDownload = origExport
})
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.NotFound(w, r)
return
}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{
"id": "slides1",
"name": "My Slides",
"mimeType": "application/vnd.google-apps.presentation",
})
}))
defer srv.Close()
svc, err := drive.NewService(context.Background(),
option.WithoutAuthentication(),
option.WithHTTPClient(srv.Client()),
option.WithEndpoint(srv.URL+"/"),
)
if err != nil {
t.Fatalf("NewService: %v", err)
}
newDriveService = func(context.Context, string) (*drive.Service, error) { return svc, nil }
var gotMime string
driveExportDownload = func(_ context.Context, _ *drive.Service, fileID string, mimeType string) (*http.Response, error) {
gotMime = mimeType
return &http.Response{
Status: "200 OK",
StatusCode: http.StatusOK,
Body: io.NopCloser(strings.NewReader("PPTX-FAKE")),
}, nil
}
dest := filepath.Join(t.TempDir(), "out")
out := captureStdout(t, func() {
_ = captureStderr(t, func() {
if err := Execute([]string{"--json", "--account", "a@b.com", "slides", "export", "slides1", "--out", dest}); err != nil {
t.Fatalf("Execute: %v", err)
}
})
})
if gotMime != "application/vnd.openxmlformats-officedocument.presentationml.presentation" {
t.Fatalf("mimeType=%q", gotMime)
}
var parsed struct {
Path string `json:"path"`
}
if err := json.Unmarshal([]byte(out), &parsed); err != nil {
t.Fatalf("json parse: %v\nout=%q", err, out)
}
if !strings.HasSuffix(parsed.Path, ".pptx") {
t.Fatalf("expected .pptx path, got %q", parsed.Path)
}
}
func TestExecute_DocsExport_RejectsNonDoc(t *testing.T) {
origNew := newDriveService
origExport := driveExportDownload
t.Cleanup(func() {
newDriveService = origNew
driveExportDownload = origExport
})
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.NotFound(w, r)
return
}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{
"id": "x",
"name": "Not a Doc",
"mimeType": "application/vnd.google-apps.spreadsheet",
})
}))
defer srv.Close()
svc, err := drive.NewService(context.Background(),
option.WithoutAuthentication(),
option.WithHTTPClient(srv.Client()),
option.WithEndpoint(srv.URL+"/"),
)
if err != nil {
t.Fatalf("NewService: %v", err)
}
newDriveService = func(context.Context, string) (*drive.Service, error) { return svc, nil }
called := false
driveExportDownload = func(context.Context, *drive.Service, string, string) (*http.Response, error) {
called = true
return nil, errors.New("unexpected export call")
}
err = Execute([]string{"--json", "--account", "a@b.com", "docs", "export", "x", "--out", filepath.Join(t.TempDir(), "out")})
if err == nil || !strings.Contains(err.Error(), "not a Google Doc") {
t.Fatalf("unexpected err=%v", err)
}
if called {
t.Fatalf("export should not be called")
}
}