300 lines
7.9 KiB
Go
300 lines
7.9 KiB
Go
package cmd
|
|
|
|
import (
|
|
"context"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"google.golang.org/api/gmail/v1"
|
|
"google.golang.org/api/option"
|
|
)
|
|
|
|
func TestExecute_GmailGet_Metadata_JSON(t *testing.T) {
|
|
origNew := newGmailService
|
|
t.Cleanup(func() { newGmailService = origNew })
|
|
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if !strings.Contains(r.URL.Path, "/gmail/v1/users/me/messages/m1") {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
if got := r.URL.Query().Get("format"); got != "metadata" {
|
|
t.Errorf("format=%q", got)
|
|
http.Error(w, "bad format", http.StatusBadRequest)
|
|
return
|
|
}
|
|
gotHeaders := r.URL.Query()["metadataHeaders"]
|
|
if len(gotHeaders) != 3 || !containsAll(gotHeaders, []string{"Subject", "Date", "List-Unsubscribe"}) {
|
|
t.Errorf("metadataHeaders=%#v", gotHeaders)
|
|
http.Error(w, "bad metadataHeaders", http.StatusBadRequest)
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(w).Encode(map[string]any{
|
|
"id": "m1",
|
|
"threadId": "t1",
|
|
"labelIds": []string{"INBOX"},
|
|
"payload": map[string]any{
|
|
"headers": []map[string]any{
|
|
{"name": "Subject", "value": "Hello"},
|
|
{"name": "Date", "value": "Wed, 17 Dec 2025 14:00:00 -0800"},
|
|
},
|
|
},
|
|
})
|
|
}))
|
|
defer srv.Close()
|
|
|
|
svc, err := gmail.NewService(context.Background(),
|
|
option.WithoutAuthentication(),
|
|
option.WithHTTPClient(srv.Client()),
|
|
option.WithEndpoint(srv.URL+"/"),
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("NewService: %v", err)
|
|
}
|
|
newGmailService = func(context.Context, string) (*gmail.Service, error) { return svc, nil }
|
|
|
|
out := captureStdout(t, func() {
|
|
_ = captureStderr(t, func() {
|
|
if err := Execute([]string{
|
|
"--json",
|
|
"--account", "a@b.com",
|
|
"gmail", "get", "m1",
|
|
"--format", "metadata",
|
|
"--headers", "Subject,Date",
|
|
}); err != nil {
|
|
t.Fatalf("Execute: %v", err)
|
|
}
|
|
})
|
|
})
|
|
|
|
var parsed struct {
|
|
Message struct {
|
|
ID string `json:"id"`
|
|
Thread string `json:"threadId"`
|
|
LabelID []string `json:"labelIds"`
|
|
} `json:"message"`
|
|
}
|
|
if err := json.Unmarshal([]byte(out), &parsed); err != nil {
|
|
t.Fatalf("json parse: %v\nout=%q", err, out)
|
|
}
|
|
if parsed.Message.ID != "m1" || parsed.Message.Thread != "t1" || len(parsed.Message.LabelID) != 1 || parsed.Message.LabelID[0] != "INBOX" {
|
|
t.Fatalf("unexpected: %#v", parsed)
|
|
}
|
|
}
|
|
|
|
func containsAll(got []string, want []string) bool {
|
|
set := map[string]bool{}
|
|
for _, g := range got {
|
|
set[g] = true
|
|
}
|
|
for _, w := range want {
|
|
if !set[w] {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func TestExecute_GmailGet_Raw_JSON(t *testing.T) {
|
|
origNew := newGmailService
|
|
t.Cleanup(func() { newGmailService = origNew })
|
|
|
|
raw := "Subject: hi\r\n\r\nbody"
|
|
rawEncoded := base64.RawURLEncoding.EncodeToString([]byte(raw))
|
|
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if !strings.Contains(r.URL.Path, "/gmail/v1/users/me/messages/m1") {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
if got := r.URL.Query().Get("format"); got != "raw" {
|
|
t.Errorf("format=%q", got)
|
|
http.Error(w, "bad format", http.StatusBadRequest)
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(w).Encode(map[string]any{
|
|
"id": "m1",
|
|
"raw": rawEncoded,
|
|
})
|
|
}))
|
|
defer srv.Close()
|
|
|
|
svc, err := gmail.NewService(context.Background(),
|
|
option.WithoutAuthentication(),
|
|
option.WithHTTPClient(srv.Client()),
|
|
option.WithEndpoint(srv.URL+"/"),
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("NewService: %v", err)
|
|
}
|
|
newGmailService = func(context.Context, string) (*gmail.Service, error) { return svc, nil }
|
|
|
|
out := captureStdout(t, func() {
|
|
_ = captureStderr(t, func() {
|
|
if err := Execute([]string{
|
|
"--json",
|
|
"--account", "a@b.com",
|
|
"gmail", "get", "m1",
|
|
"--format", "raw",
|
|
}); err != nil {
|
|
t.Fatalf("Execute: %v", err)
|
|
}
|
|
})
|
|
})
|
|
|
|
var parsed struct {
|
|
Message struct {
|
|
ID string `json:"id"`
|
|
Raw string `json:"raw"`
|
|
} `json:"message"`
|
|
}
|
|
if err := json.Unmarshal([]byte(out), &parsed); err != nil {
|
|
t.Fatalf("json parse: %v\nout=%q", err, out)
|
|
}
|
|
if parsed.Message.ID != "m1" || parsed.Message.Raw != rawEncoded {
|
|
t.Fatalf("unexpected: %#v", parsed)
|
|
}
|
|
}
|
|
|
|
func TestExecute_GmailGet_Full_JSON_Body(t *testing.T) {
|
|
origNew := newGmailService
|
|
t.Cleanup(func() { newGmailService = origNew })
|
|
|
|
plain := base64.RawURLEncoding.EncodeToString([]byte("plain body"))
|
|
html := base64.RawURLEncoding.EncodeToString([]byte("<p>html body</p>"))
|
|
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if !strings.Contains(r.URL.Path, "/gmail/v1/users/me/messages/m1") {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
if got := r.URL.Query().Get("format"); got != "full" {
|
|
t.Errorf("format=%q", got)
|
|
http.Error(w, "bad format", http.StatusBadRequest)
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(w).Encode(map[string]any{
|
|
"id": "m1",
|
|
"payload": map[string]any{
|
|
"mimeType": "multipart/alternative",
|
|
"parts": []map[string]any{
|
|
{"mimeType": "text/html", "body": map[string]any{"data": html}},
|
|
{"mimeType": "text/plain; charset=utf-8", "body": map[string]any{"data": plain}},
|
|
},
|
|
},
|
|
})
|
|
}))
|
|
defer srv.Close()
|
|
|
|
svc, err := gmail.NewService(context.Background(),
|
|
option.WithoutAuthentication(),
|
|
option.WithHTTPClient(srv.Client()),
|
|
option.WithEndpoint(srv.URL+"/"),
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("NewService: %v", err)
|
|
}
|
|
newGmailService = func(context.Context, string) (*gmail.Service, error) { return svc, nil }
|
|
|
|
out := captureStdout(t, func() {
|
|
_ = captureStderr(t, func() {
|
|
if err := Execute([]string{
|
|
"--json",
|
|
"--account", "a@b.com",
|
|
"gmail", "get", "m1",
|
|
}); err != nil {
|
|
t.Fatalf("Execute: %v", err)
|
|
}
|
|
})
|
|
})
|
|
|
|
var parsed struct {
|
|
Body string `json:"body"`
|
|
}
|
|
if err := json.Unmarshal([]byte(out), &parsed); err != nil {
|
|
t.Fatalf("json parse: %v\nout=%q", err, out)
|
|
}
|
|
if parsed.Body != "plain body" {
|
|
t.Fatalf("unexpected body: %q", parsed.Body)
|
|
}
|
|
}
|
|
|
|
func TestExecute_GmailGet_InvalidFormat(t *testing.T) {
|
|
_ = captureStderr(t, func() {
|
|
err := Execute([]string{
|
|
"--account", "a@b.com",
|
|
"gmail", "get", "m1",
|
|
"--format", "nope",
|
|
})
|
|
if err == nil {
|
|
t.Fatalf("expected error")
|
|
}
|
|
if !strings.Contains(err.Error(), "invalid --format") {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestExecute_GmailGet_Metadata_Text(t *testing.T) {
|
|
origNew := newGmailService
|
|
t.Cleanup(func() { newGmailService = origNew })
|
|
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if !strings.Contains(r.URL.Path, "/gmail/v1/users/me/messages/m1") {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
if got := r.URL.Query().Get("format"); got != "metadata" {
|
|
t.Errorf("format=%q", got)
|
|
http.Error(w, "bad format", http.StatusBadRequest)
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(w).Encode(map[string]any{
|
|
"id": "m1",
|
|
"threadId": "t1",
|
|
"labelIds": []string{"INBOX"},
|
|
"payload": map[string]any{
|
|
"headers": []map[string]any{
|
|
{"name": "From", "value": "Me <me@example.com>"},
|
|
{"name": "Subject", "value": "Hello"},
|
|
},
|
|
},
|
|
})
|
|
}))
|
|
defer srv.Close()
|
|
|
|
svc, err := gmail.NewService(context.Background(),
|
|
option.WithoutAuthentication(),
|
|
option.WithHTTPClient(srv.Client()),
|
|
option.WithEndpoint(srv.URL+"/"),
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("NewService: %v", err)
|
|
}
|
|
newGmailService = func(context.Context, string) (*gmail.Service, error) { return svc, nil }
|
|
|
|
out := captureStdout(t, func() {
|
|
_ = captureStderr(t, func() {
|
|
if err := Execute([]string{
|
|
"--account", "a@b.com",
|
|
"gmail", "get", "m1",
|
|
"--format", "metadata",
|
|
"--headers", "From,Subject",
|
|
}); err != nil {
|
|
t.Fatalf("Execute: %v", err)
|
|
}
|
|
})
|
|
})
|
|
if !strings.Contains(out, "id\tm1") || !strings.Contains(out, "subject\tHello") {
|
|
t.Fatalf("unexpected out=%q", out)
|
|
}
|
|
}
|