* feat(cli): improve agent ergonomics * fix(cli): address code review findings - Fix nil pointer dereference in confirmDestructive when flags is nil - Deduplicate dry-run logic by delegating to dryRunExit - Remove deprecated net.Error.Temporary() call (dead since Go 1.18) - Add unit tests for resolveTasklistID and resolveCalendarID Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: resolve PR #201 conflicts and follow-ups (#201) (thanks @salmonumbrella) * fix: resolve rebase fallout for PR #201 landing (#201) (thanks @salmonumbrella) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Peter Steinberger <steipete@gmail.com>
556 lines
17 KiB
Go
556 lines
17 KiB
Go
package cmd
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"google.golang.org/api/gmail/v1"
|
|
"google.golang.org/api/option"
|
|
|
|
"github.com/steipete/gogcli/internal/outfmt"
|
|
"github.com/steipete/gogcli/internal/ui"
|
|
)
|
|
|
|
func TestGmailSendAsListCmd_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, "/settings/sendAs") && r.Method == http.MethodGet {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(w).Encode(map[string]any{
|
|
"sendAs": []map[string]any{
|
|
{
|
|
"sendAsEmail": "primary@example.com",
|
|
"displayName": "Primary User",
|
|
"isDefault": true,
|
|
"isPrimary": true,
|
|
"treatAsAlias": false,
|
|
"verificationStatus": "accepted",
|
|
},
|
|
{
|
|
"sendAsEmail": "work@company.com",
|
|
"displayName": "Work Alias",
|
|
"isDefault": false,
|
|
"isPrimary": false,
|
|
"treatAsAlias": true,
|
|
"verificationStatus": "accepted",
|
|
},
|
|
},
|
|
})
|
|
return
|
|
}
|
|
http.NotFound(w, r)
|
|
}))
|
|
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 }
|
|
|
|
flags := &RootFlags{Account: "a@b.com", Force: true}
|
|
|
|
out := captureStdout(t, func() {
|
|
u, uiErr := ui.New(ui.Options{Stdout: io.Discard, Stderr: io.Discard, Color: "never"})
|
|
if uiErr != nil {
|
|
t.Fatalf("ui.New: %v", uiErr)
|
|
}
|
|
ctx := ui.WithUI(context.Background(), u)
|
|
ctx = outfmt.WithMode(ctx, outfmt.Mode{JSON: true})
|
|
|
|
if err := runKong(t, &GmailSendAsListCmd{}, []string{}, ctx, flags); err != nil {
|
|
t.Fatalf("execute: %v", err)
|
|
}
|
|
})
|
|
|
|
var parsed struct {
|
|
SendAs []struct {
|
|
SendAsEmail string `json:"sendAsEmail"`
|
|
DisplayName string `json:"displayName"`
|
|
IsDefault bool `json:"isDefault"`
|
|
VerificationStatus string `json:"verificationStatus"`
|
|
} `json:"sendAs"`
|
|
}
|
|
if err := json.Unmarshal([]byte(out), &parsed); err != nil {
|
|
t.Fatalf("json parse: %v\nout=%q", err, out)
|
|
}
|
|
if len(parsed.SendAs) != 2 {
|
|
t.Fatalf("unexpected sendAs count: %d", len(parsed.SendAs))
|
|
}
|
|
if parsed.SendAs[0].SendAsEmail != "primary@example.com" {
|
|
t.Fatalf("unexpected first sendAs: %#v", parsed.SendAs[0])
|
|
}
|
|
if parsed.SendAs[1].SendAsEmail != "work@company.com" {
|
|
t.Fatalf("unexpected second sendAs: %#v", parsed.SendAs[1])
|
|
}
|
|
}
|
|
|
|
func TestGmailSendAsGetCmd_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, "/settings/sendAs/work@company.com") && r.Method == http.MethodGet {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(w).Encode(map[string]any{
|
|
"sendAsEmail": "work@company.com",
|
|
"displayName": "Work Alias",
|
|
"replyToAddress": "replies@company.com",
|
|
"signature": "<b>Signature</b>",
|
|
"isDefault": false,
|
|
"isPrimary": false,
|
|
"treatAsAlias": true,
|
|
"verificationStatus": "accepted",
|
|
})
|
|
return
|
|
}
|
|
http.NotFound(w, r)
|
|
}))
|
|
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 }
|
|
|
|
flags := &RootFlags{Account: "a@b.com", Force: true}
|
|
|
|
out := captureStdout(t, func() {
|
|
u, uiErr := ui.New(ui.Options{Stdout: io.Discard, Stderr: io.Discard, Color: "never"})
|
|
if uiErr != nil {
|
|
t.Fatalf("ui.New: %v", uiErr)
|
|
}
|
|
ctx := ui.WithUI(context.Background(), u)
|
|
ctx = outfmt.WithMode(ctx, outfmt.Mode{JSON: true})
|
|
|
|
if err := runKong(t, &GmailSendAsGetCmd{}, []string{"work@company.com"}, ctx, flags); err != nil {
|
|
t.Fatalf("execute: %v", err)
|
|
}
|
|
})
|
|
|
|
var parsed struct {
|
|
SendAs struct {
|
|
SendAsEmail string `json:"sendAsEmail"`
|
|
DisplayName string `json:"displayName"`
|
|
ReplyToAddress string `json:"replyToAddress"`
|
|
VerificationStatus string `json:"verificationStatus"`
|
|
} `json:"sendAs"`
|
|
}
|
|
if err := json.Unmarshal([]byte(out), &parsed); err != nil {
|
|
t.Fatalf("json parse: %v\nout=%q", err, out)
|
|
}
|
|
if parsed.SendAs.SendAsEmail != "work@company.com" {
|
|
t.Fatalf("unexpected sendAs: %#v", parsed.SendAs)
|
|
}
|
|
if parsed.SendAs.DisplayName != "Work Alias" {
|
|
t.Fatalf("unexpected displayName: %q", parsed.SendAs.DisplayName)
|
|
}
|
|
}
|
|
|
|
func TestGmailBatchDeleteCmd_JSON(t *testing.T) {
|
|
origNew := newGmailService
|
|
t.Cleanup(func() { newGmailService = origNew })
|
|
|
|
var receivedIDs []string
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if strings.Contains(r.URL.Path, "/messages/batchDelete") && r.Method == http.MethodPost {
|
|
var body struct {
|
|
IDs []string `json:"ids"`
|
|
}
|
|
_ = json.NewDecoder(r.Body).Decode(&body)
|
|
receivedIDs = body.IDs
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusNoContent)
|
|
return
|
|
}
|
|
http.NotFound(w, r)
|
|
}))
|
|
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 }
|
|
|
|
flags := &RootFlags{Account: "a@b.com", Force: true}
|
|
|
|
out := captureStdout(t, func() {
|
|
u, uiErr := ui.New(ui.Options{Stdout: io.Discard, Stderr: io.Discard, Color: "never"})
|
|
if uiErr != nil {
|
|
t.Fatalf("ui.New: %v", uiErr)
|
|
}
|
|
ctx := ui.WithUI(context.Background(), u)
|
|
ctx = outfmt.WithMode(ctx, outfmt.Mode{JSON: true})
|
|
|
|
if err := runKong(t, &GmailBatchDeleteCmd{}, []string{"msg1", "msg2", "msg3"}, ctx, flags); err != nil {
|
|
t.Fatalf("execute: %v", err)
|
|
}
|
|
})
|
|
|
|
if len(receivedIDs) != 3 || receivedIDs[0] != "msg1" {
|
|
t.Fatalf("unexpected IDs sent: %v", receivedIDs)
|
|
}
|
|
|
|
var parsed struct {
|
|
Deleted []string `json:"deleted"`
|
|
Count int `json:"count"`
|
|
}
|
|
if err := json.Unmarshal([]byte(out), &parsed); err != nil {
|
|
t.Fatalf("json parse: %v\nout=%q", err, out)
|
|
}
|
|
if parsed.Count != 3 {
|
|
t.Fatalf("unexpected count: %d", parsed.Count)
|
|
}
|
|
}
|
|
|
|
func TestGmailBatchModifyCmd_JSON(t *testing.T) {
|
|
origNew := newGmailService
|
|
t.Cleanup(func() { newGmailService = origNew })
|
|
|
|
var receivedRequest struct {
|
|
IDs []string `json:"ids"`
|
|
AddLabelIds []string `json:"addLabelIds"`
|
|
RemoveLabelIds []string `json:"removeLabelIds"`
|
|
}
|
|
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
switch {
|
|
case r.Method == http.MethodGet && strings.Contains(r.URL.Path, "/users/me/labels"):
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(w).Encode(map[string]any{
|
|
"labels": []map[string]any{
|
|
{"id": "INBOX", "name": "INBOX", "type": "system"},
|
|
{"id": "SPAM", "name": "SPAM", "type": "system"},
|
|
},
|
|
})
|
|
return
|
|
case strings.Contains(r.URL.Path, "/messages/batchModify") && r.Method == http.MethodPost:
|
|
_ = json.NewDecoder(r.Body).Decode(&receivedRequest)
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusNoContent)
|
|
return
|
|
}
|
|
http.NotFound(w, r)
|
|
}))
|
|
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 }
|
|
|
|
flags := &RootFlags{Account: "a@b.com", Force: true}
|
|
|
|
out := captureStdout(t, func() {
|
|
u, uiErr := ui.New(ui.Options{Stdout: io.Discard, Stderr: io.Discard, Color: "never"})
|
|
if uiErr != nil {
|
|
t.Fatalf("ui.New: %v", uiErr)
|
|
}
|
|
ctx := ui.WithUI(context.Background(), u)
|
|
ctx = outfmt.WithMode(ctx, outfmt.Mode{JSON: true})
|
|
|
|
if err := runKong(t, &GmailBatchModifyCmd{}, []string{
|
|
"msg1", "msg2",
|
|
"--add", "INBOX",
|
|
"--remove", "SPAM",
|
|
}, ctx, flags); err != nil {
|
|
t.Fatalf("execute: %v", err)
|
|
}
|
|
})
|
|
|
|
if len(receivedRequest.IDs) != 2 {
|
|
t.Fatalf("unexpected IDs: %v", receivedRequest.IDs)
|
|
}
|
|
if len(receivedRequest.AddLabelIds) != 1 || receivedRequest.AddLabelIds[0] != "INBOX" {
|
|
t.Fatalf("unexpected addLabelIds: %v", receivedRequest.AddLabelIds)
|
|
}
|
|
if len(receivedRequest.RemoveLabelIds) != 1 || receivedRequest.RemoveLabelIds[0] != "SPAM" {
|
|
t.Fatalf("unexpected removeLabelIds: %v", receivedRequest.RemoveLabelIds)
|
|
}
|
|
|
|
var parsed struct {
|
|
Modified []string `json:"modified"`
|
|
Count int `json:"count"`
|
|
}
|
|
if err := json.Unmarshal([]byte(out), &parsed); err != nil {
|
|
t.Fatalf("json parse: %v\nout=%q", err, out)
|
|
}
|
|
if parsed.Count != 2 {
|
|
t.Fatalf("unexpected count: %d", parsed.Count)
|
|
}
|
|
}
|
|
|
|
func TestGmailSendAsCreateCmd_JSON(t *testing.T) {
|
|
origNew := newGmailService
|
|
t.Cleanup(func() { newGmailService = origNew })
|
|
|
|
var receivedBody map[string]any
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if strings.Contains(r.URL.Path, "/settings/sendAs") && r.Method == http.MethodPost {
|
|
_ = json.NewDecoder(r.Body).Decode(&receivedBody)
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(w).Encode(map[string]any{
|
|
"sendAsEmail": "alias@example.com",
|
|
"displayName": "Test Alias",
|
|
"verificationStatus": "pending",
|
|
})
|
|
return
|
|
}
|
|
http.NotFound(w, r)
|
|
}))
|
|
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 }
|
|
|
|
flags := &RootFlags{Account: "a@b.com", Force: true}
|
|
|
|
out := captureStdout(t, func() {
|
|
u, uiErr := ui.New(ui.Options{Stdout: io.Discard, Stderr: io.Discard, Color: "never"})
|
|
if uiErr != nil {
|
|
t.Fatalf("ui.New: %v", uiErr)
|
|
}
|
|
ctx := ui.WithUI(context.Background(), u)
|
|
ctx = outfmt.WithMode(ctx, outfmt.Mode{JSON: true})
|
|
|
|
if err := runKong(t, &GmailSendAsCreateCmd{}, []string{
|
|
"alias@example.com",
|
|
"--display-name", "Test Alias",
|
|
}, ctx, flags); err != nil {
|
|
t.Fatalf("execute: %v", err)
|
|
}
|
|
})
|
|
|
|
var parsed struct {
|
|
SendAs struct {
|
|
SendAsEmail string `json:"sendAsEmail"`
|
|
VerificationStatus string `json:"verificationStatus"`
|
|
} `json:"sendAs"`
|
|
}
|
|
if err := json.Unmarshal([]byte(out), &parsed); err != nil {
|
|
t.Fatalf("json parse: %v\nout=%q", err, out)
|
|
}
|
|
if parsed.SendAs.SendAsEmail != "alias@example.com" {
|
|
t.Fatalf("unexpected sendAs: %#v", parsed.SendAs)
|
|
}
|
|
if parsed.SendAs.VerificationStatus != "pending" {
|
|
t.Fatalf("unexpected status: %q", parsed.SendAs.VerificationStatus)
|
|
}
|
|
}
|
|
|
|
func TestGmailSendAsDeleteCmd_JSON(t *testing.T) {
|
|
origNew := newGmailService
|
|
t.Cleanup(func() { newGmailService = origNew })
|
|
|
|
var deletedEmail string
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if strings.Contains(r.URL.Path, "/settings/sendAs/") && r.Method == http.MethodDelete {
|
|
parts := strings.Split(r.URL.Path, "/")
|
|
deletedEmail = parts[len(parts)-1]
|
|
w.WriteHeader(http.StatusNoContent)
|
|
return
|
|
}
|
|
http.NotFound(w, r)
|
|
}))
|
|
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 }
|
|
|
|
flags := &RootFlags{Account: "a@b.com", Force: true}
|
|
|
|
out := captureStdout(t, func() {
|
|
u, uiErr := ui.New(ui.Options{Stdout: io.Discard, Stderr: io.Discard, Color: "never"})
|
|
if uiErr != nil {
|
|
t.Fatalf("ui.New: %v", uiErr)
|
|
}
|
|
ctx := ui.WithUI(context.Background(), u)
|
|
ctx = outfmt.WithMode(ctx, outfmt.Mode{JSON: true})
|
|
|
|
if err := runKong(t, &GmailSendAsDeleteCmd{}, []string{"delete-me@example.com"}, ctx, flags); err != nil {
|
|
t.Fatalf("execute: %v", err)
|
|
}
|
|
})
|
|
|
|
if deletedEmail != "delete-me@example.com" {
|
|
t.Fatalf("unexpected deleted email: %q", deletedEmail)
|
|
}
|
|
|
|
var parsed struct {
|
|
Email string `json:"email"`
|
|
Deleted bool `json:"deleted"`
|
|
}
|
|
if err := json.Unmarshal([]byte(out), &parsed); err != nil {
|
|
t.Fatalf("json parse: %v\nout=%q", err, out)
|
|
}
|
|
if !parsed.Deleted {
|
|
t.Fatalf("expected deleted=true")
|
|
}
|
|
}
|
|
|
|
func TestGmailSendAsVerifyCmd_JSON(t *testing.T) {
|
|
origNew := newGmailService
|
|
t.Cleanup(func() { newGmailService = origNew })
|
|
|
|
var verifiedEmail string
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if strings.Contains(r.URL.Path, "/settings/sendAs/") && strings.HasSuffix(r.URL.Path, "/verify") && r.Method == http.MethodPost {
|
|
parts := strings.Split(r.URL.Path, "/")
|
|
verifiedEmail = parts[len(parts)-2]
|
|
w.WriteHeader(http.StatusNoContent)
|
|
return
|
|
}
|
|
http.NotFound(w, r)
|
|
}))
|
|
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 }
|
|
|
|
flags := &RootFlags{Account: "a@b.com"}
|
|
|
|
out := captureStdout(t, func() {
|
|
u, uiErr := ui.New(ui.Options{Stdout: io.Discard, Stderr: io.Discard, Color: "never"})
|
|
if uiErr != nil {
|
|
t.Fatalf("ui.New: %v", uiErr)
|
|
}
|
|
ctx := ui.WithUI(context.Background(), u)
|
|
ctx = outfmt.WithMode(ctx, outfmt.Mode{JSON: true})
|
|
|
|
if err := runKong(t, &GmailSendAsVerifyCmd{}, []string{"verify-me@example.com"}, ctx, flags); err != nil {
|
|
t.Fatalf("execute: %v", err)
|
|
}
|
|
})
|
|
|
|
if verifiedEmail != "verify-me@example.com" {
|
|
t.Fatalf("unexpected verified email: %q", verifiedEmail)
|
|
}
|
|
|
|
var parsed struct {
|
|
Email string `json:"email"`
|
|
Message string `json:"message"`
|
|
}
|
|
if err := json.Unmarshal([]byte(out), &parsed); err != nil {
|
|
t.Fatalf("json parse: %v\nout=%q", err, out)
|
|
}
|
|
if parsed.Email != "verify-me@example.com" {
|
|
t.Fatalf("unexpected email: %q", parsed.Email)
|
|
}
|
|
}
|
|
|
|
func TestGmailSendAsUpdateCmd_JSON(t *testing.T) {
|
|
origNew := newGmailService
|
|
t.Cleanup(func() { newGmailService = origNew })
|
|
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
switch {
|
|
case strings.Contains(r.URL.Path, "/settings/sendAs/update@example.com") && r.Method == http.MethodGet:
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(w).Encode(map[string]any{
|
|
"sendAsEmail": "update@example.com",
|
|
"displayName": "Old Name",
|
|
"verificationStatus": "accepted",
|
|
})
|
|
return
|
|
case strings.Contains(r.URL.Path, "/settings/sendAs/update@example.com") && r.Method == http.MethodPut:
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(w).Encode(map[string]any{
|
|
"sendAsEmail": "update@example.com",
|
|
"displayName": "New Name",
|
|
"verificationStatus": "accepted",
|
|
})
|
|
return
|
|
}
|
|
http.NotFound(w, r)
|
|
}))
|
|
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 }
|
|
|
|
flags := &RootFlags{Account: "a@b.com"}
|
|
|
|
out := captureStdout(t, func() {
|
|
u, uiErr := ui.New(ui.Options{Stdout: io.Discard, Stderr: io.Discard, Color: "never"})
|
|
if uiErr != nil {
|
|
t.Fatalf("ui.New: %v", uiErr)
|
|
}
|
|
ctx := ui.WithUI(context.Background(), u)
|
|
ctx = outfmt.WithMode(ctx, outfmt.Mode{JSON: true})
|
|
|
|
if err := runKong(t, &GmailSendAsUpdateCmd{}, []string{
|
|
"update@example.com",
|
|
"--display-name", "New Name",
|
|
}, ctx, flags); err != nil {
|
|
t.Fatalf("execute: %v", err)
|
|
}
|
|
})
|
|
|
|
var parsed struct {
|
|
SendAs struct {
|
|
SendAsEmail string `json:"sendAsEmail"`
|
|
DisplayName string `json:"displayName"`
|
|
} `json:"sendAs"`
|
|
}
|
|
if err := json.Unmarshal([]byte(out), &parsed); err != nil {
|
|
t.Fatalf("json parse: %v\nout=%q", err, out)
|
|
}
|
|
if parsed.SendAs.DisplayName != "New Name" {
|
|
t.Fatalf("unexpected displayName: %q", parsed.SendAs.DisplayName)
|
|
}
|
|
}
|