Skip to content

Commit d45d47a

Browse files
committed
fix(mail): update tests for signature auto-resolve changes
- Add senderEmailHint param to buildRawEMLForDraftCreate to avoid duplicate profile API calls when Execute already resolved the sender - Update signature_compose_test: replace deleted validateSignatureWithPlainText test with validateNoSignatureConflict tests - Update mail_draft_create_test: add new senderEmailHint arg to all buildRawEMLForDraftCreate call sites sprint: S1
1 parent f180460 commit d45d47a

3 files changed

Lines changed: 83 additions & 22 deletions

File tree

shortcuts/mail/mail_draft_create.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ var MailDraftCreate = common.Shortcut{
195195
return err
196196
}
197197
rawEML, lintApplied, lintBlocked, err := buildRawEMLForDraftCreate(ctx, runtime, input, sigResult, priority,
198-
templateLargeAttachmentIDs, mailboxID, templateID, templateInlineAttachments, templateSmallAttachments)
198+
templateLargeAttachmentIDs, mailboxID, templateID, templateInlineAttachments, templateSmallAttachments, senderEmail)
199199
if err != nil {
200200
return err
201201
}
@@ -251,13 +251,19 @@ func buildRawEMLForDraftCreate(
251251
mailboxID, templateID string,
252252
templateInlineAttachments []templateInlineRef,
253253
templateSmallAttachments []templateAttachmentRef,
254+
senderEmailHint string,
254255
) (rawEMLOut string, lintApplied, lintBlocked []lint.Finding, err error) {
255256
// Initialise lint findings as empty (non-nil) slices so callers can
256257
// surface them through the envelope unconditionally even on the
257258
// plain-text branch.
258259
lintApplied, lintBlocked = emptyLintFindings()
259260

260-
senderEmail := resolveComposeSenderEmail(runtime)
261+
// Use the pre-resolved senderEmail when available (avoids a duplicate
262+
// profile API call when Execute already fetched it for auto-resolve).
263+
senderEmail := senderEmailHint
264+
if senderEmail == "" {
265+
senderEmail = resolveComposeSenderEmail(runtime)
266+
}
261267
if senderEmail == "" {
262268
return "", lintApplied, lintBlocked, mailValidationParamError("--from", "unable to determine sender email; please specify --from explicitly")
263269
}

shortcuts/mail/mail_draft_create_test.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func TestBuildRawEMLForDraftCreate_ResolvesLocalImages(t *testing.T) {
6262
Body: `<p>Hello</p><p><img src="./test_image.png" /></p>`,
6363
}
6464

65-
rawEML, _, _, err := buildRawEMLForDraftCreate(context.Background(), newRuntimeWithFrom("sender@example.com"), input, nil, "", nil, "", "", nil, nil)
65+
rawEML, _, _, err := buildRawEMLForDraftCreate(context.Background(), newRuntimeWithFrom("sender@example.com"), input, nil, "", nil, "", "", nil, nil, "")
6666
if err != nil {
6767
t.Fatalf("buildRawEMLForDraftCreate() error = %v", err)
6868
}
@@ -88,7 +88,7 @@ func TestBuildRawEMLForDraftCreate_NoLocalImages(t *testing.T) {
8888
Body: `<p>Hello <b>world</b></p>`,
8989
}
9090

91-
rawEML, _, _, err := buildRawEMLForDraftCreate(context.Background(), newRuntimeWithFrom("sender@example.com"), input, nil, "", nil, "", "", nil, nil)
91+
rawEML, _, _, err := buildRawEMLForDraftCreate(context.Background(), newRuntimeWithFrom("sender@example.com"), input, nil, "", nil, "", "", nil, nil, "")
9292
if err != nil {
9393
t.Fatalf("buildRawEMLForDraftCreate() error = %v", err)
9494
}
@@ -124,7 +124,7 @@ func TestBuildRawEMLForDraftCreate_AutoResolveCountedInSizeLimit(t *testing.T) {
124124
Attach: "./big.txt",
125125
}
126126

127-
_, _, _, err := buildRawEMLForDraftCreate(context.Background(), newRuntimeWithFrom("sender@example.com"), input, nil, "", nil, "", "", nil, nil)
127+
_, _, _, err := buildRawEMLForDraftCreate(context.Background(), newRuntimeWithFrom("sender@example.com"), input, nil, "", nil, "", "", nil, nil, "")
128128
if err == nil {
129129
t.Fatal("expected size limit error when auto-resolved image + attachment exceed 25MB")
130130
}
@@ -145,7 +145,7 @@ func TestBuildRawEMLForDraftCreate_OrphanedInlineSpecError(t *testing.T) {
145145
Inline: `[{"cid":"orphan","file_path":"./unused.png"}]`,
146146
}
147147

148-
_, _, _, err := buildRawEMLForDraftCreate(context.Background(), newRuntimeWithFrom("sender@example.com"), input, nil, "", nil, "", "", nil, nil)
148+
_, _, _, err := buildRawEMLForDraftCreate(context.Background(), newRuntimeWithFrom("sender@example.com"), input, nil, "", nil, "", "", nil, nil, "")
149149
if err == nil {
150150
t.Fatal("expected error for orphaned --inline CID not referenced in body")
151151
}
@@ -166,7 +166,7 @@ func TestBuildRawEMLForDraftCreate_MissingCIDRefError(t *testing.T) {
166166
Inline: `[{"cid":"present","file_path":"./present.png"}]`,
167167
}
168168

169-
_, _, _, err := buildRawEMLForDraftCreate(context.Background(), newRuntimeWithFrom("sender@example.com"), input, nil, "", nil, "", "", nil, nil)
169+
_, _, _, err := buildRawEMLForDraftCreate(context.Background(), newRuntimeWithFrom("sender@example.com"), input, nil, "", nil, "", "", nil, nil, "")
170170
if err == nil {
171171
t.Fatal("expected error for missing CID reference")
172172
}
@@ -183,7 +183,7 @@ func TestBuildRawEMLForDraftCreate_WithPriority(t *testing.T) {
183183
Body: `<p>Hello</p>`,
184184
}
185185

186-
rawEML, _, _, err := buildRawEMLForDraftCreate(context.Background(), newRuntimeWithFrom("sender@example.com"), input, nil, "1", nil, "", "", nil, nil)
186+
rawEML, _, _, err := buildRawEMLForDraftCreate(context.Background(), newRuntimeWithFrom("sender@example.com"), input, nil, "1", nil, "", "", nil, nil, "")
187187
if err != nil {
188188
t.Fatalf("buildRawEMLForDraftCreate() error = %v", err)
189189
}
@@ -201,7 +201,7 @@ func TestBuildRawEMLForDraftCreate_NoPriority(t *testing.T) {
201201
Body: `<p>Hello</p>`,
202202
}
203203

204-
rawEML, _, _, err := buildRawEMLForDraftCreate(context.Background(), newRuntimeWithFrom("sender@example.com"), input, nil, "", nil, "", "", nil, nil)
204+
rawEML, _, _, err := buildRawEMLForDraftCreate(context.Background(), newRuntimeWithFrom("sender@example.com"), input, nil, "", nil, "", "", nil, nil, "")
205205
if err != nil {
206206
t.Fatalf("buildRawEMLForDraftCreate() error = %v", err)
207207
}
@@ -237,7 +237,7 @@ func TestBuildRawEMLForDraftCreate_RequestReceiptAddsHeader(t *testing.T) {
237237
}
238238

239239
rawEML, _, _, err := buildRawEMLForDraftCreate(context.Background(),
240-
newRuntimeWithFromAndRequestReceipt("sender@example.com", true), input, nil, "", nil, "", "", nil, nil)
240+
newRuntimeWithFromAndRequestReceipt("sender@example.com", true), input, nil, "", nil, "", "", nil, nil, "")
241241
if err != nil {
242242
t.Fatalf("buildRawEMLForDraftCreate() error = %v", err)
243243
}
@@ -260,7 +260,7 @@ func TestBuildRawEMLForDraftCreate_RequestReceiptOmittedByDefault(t *testing.T)
260260
}
261261

262262
rawEML, _, _, err := buildRawEMLForDraftCreate(context.Background(),
263-
newRuntimeWithFromAndRequestReceipt("sender@example.com", false), input, nil, "", nil, "", "", nil, nil)
263+
newRuntimeWithFromAndRequestReceipt("sender@example.com", false), input, nil, "", nil, "", "", nil, nil, "")
264264
if err != nil {
265265
t.Fatalf("buildRawEMLForDraftCreate() error = %v", err)
266266
}
@@ -283,7 +283,7 @@ func TestBuildRawEMLForDraftCreate_PlainTextSkipsResolve(t *testing.T) {
283283
PlainText: true,
284284
}
285285

286-
rawEML, _, _, err := buildRawEMLForDraftCreate(context.Background(), newRuntimeWithFrom("sender@example.com"), input, nil, "", nil, "", "", nil, nil)
286+
rawEML, _, _, err := buildRawEMLForDraftCreate(context.Background(), newRuntimeWithFrom("sender@example.com"), input, nil, "", nil, "", "", nil, nil, "")
287287
if err != nil {
288288
t.Fatalf("buildRawEMLForDraftCreate() error = %v", err)
289289
}
@@ -304,7 +304,7 @@ func TestBuildRawEMLForDraftCreate_WithCalendarEvent(t *testing.T) {
304304
Body: "<p>Please join us</p>",
305305
}
306306

307-
rawEML, _, _, err := buildRawEMLForDraftCreate(context.Background(), rt, input, nil, "", nil, "", "", nil, nil)
307+
rawEML, _, _, err := buildRawEMLForDraftCreate(context.Background(), rt, input, nil, "", nil, "", "", nil, nil, "")
308308
if err != nil {
309309
t.Fatalf("buildRawEMLForDraftCreate() error = %v", err)
310310
}

shortcuts/mail/signature_compose_test.go

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"testing"
1313

1414
"github.com/larksuite/cli/errs"
15+
"github.com/larksuite/cli/internal/output"
1516
)
1617

1718
func TestDownloadSignatureImageRejectsInvalidURLs(t *testing.T) {
@@ -174,17 +175,71 @@ func TestDownloadSignatureImageSuccessUsesFilenameContentType(t *testing.T) {
174175
}
175176
}
176177

177-
func TestValidateSignatureWithPlainTextTypedError(t *testing.T) {
178-
err := validateSignatureWithPlainText(true, "sig_123")
179-
var validationErr *errs.ValidationError
180-
if !errors.As(err, &validationErr) {
181-
t.Fatalf("expected validation error, got %T (%v)", err, err)
178+
func TestValidateNoSignatureConflictTypedError(t *testing.T) {
179+
err := validateNoSignatureConflict(true, "sig_123")
180+
if err == nil {
181+
t.Fatal("expected error, got nil")
182182
}
183-
if len(validationErr.Params) != 2 {
184-
t.Fatalf("params = %#v, want two conflicting params", validationErr.Params)
183+
// output.ErrValidation returns *output.ExitError with exit code ExitValidation (2).
184+
var exitErr *output.ExitError
185+
if !errors.As(err, &exitErr) {
186+
t.Fatalf("expected *output.ExitError, got %T (%v)", err, err)
185187
}
186-
if validationErr.Params[0].Name != "--plain-text" || validationErr.Params[1].Name != "--signature-id" {
187-
t.Fatalf("unexpected params: %#v", validationErr.Params)
188+
if exitErr.Code != output.ExitValidation {
189+
t.Fatalf("exit code = %d, want %d (ExitValidation)", exitErr.Code, output.ExitValidation)
190+
}
191+
if !strings.Contains(err.Error(), "mutually exclusive") {
192+
t.Fatalf("error message = %q, want it to contain \"mutually exclusive\"", err.Error())
193+
}
194+
}
195+
196+
func TestValidateNoSignatureConflictNoError(t *testing.T) {
197+
if err := validateNoSignatureConflict(false, "sig_123"); err != nil {
198+
t.Fatalf("expected no error when noSignature=false, got %v", err)
199+
}
200+
if err := validateNoSignatureConflict(true, ""); err != nil {
201+
t.Fatalf("expected no error when signatureID empty, got %v", err)
202+
}
203+
}
204+
205+
func TestInjectPlainTextSignatureNilSig(t *testing.T) {
206+
body := "Hello world"
207+
got := injectPlainTextSignature(body, nil)
208+
if got != body {
209+
t.Fatalf("expected unchanged body %q, got %q", body, got)
210+
}
211+
}
212+
213+
func TestInjectPlainTextSignatureEmptyHTML(t *testing.T) {
214+
sig := &signatureResult{RenderedContent: " <br> "}
215+
body := "Hello world"
216+
got := injectPlainTextSignature(body, sig)
217+
// PlainTextFromHTML on whitespace-only HTML collapses to empty → no change
218+
if got != body {
219+
t.Fatalf("expected unchanged body for empty HTML sig, got %q", got)
220+
}
221+
}
222+
223+
func TestInjectPlainTextSignatureAppendsWithBlankLine(t *testing.T) {
224+
sig := &signatureResult{RenderedContent: "<div>Best,<br>Bob</div>"}
225+
body := "Hello world"
226+
got := injectPlainTextSignature(body, sig)
227+
if !strings.HasPrefix(got, body+"\n\n") {
228+
t.Fatalf("expected body followed by two newlines, got %q", got)
229+
}
230+
if !strings.Contains(got, "Best,") || !strings.Contains(got, "Bob") {
231+
t.Fatalf("expected sig text in result, got %q", got)
232+
}
233+
}
234+
235+
func TestInjectPlainTextSignatureTrimsTrailingNewlines(t *testing.T) {
236+
// RenderedContent whose plain-text rendering ends in newlines — they must be trimmed.
237+
sig := &signatureResult{RenderedContent: "<p>Alice</p>"}
238+
body := "My message"
239+
got := injectPlainTextSignature(body, sig)
240+
// Result must not end with a bare newline after the signature text.
241+
if strings.HasSuffix(got, "\n") {
242+
t.Fatalf("result should not end with newline, got %q", got)
188243
}
189244
}
190245

0 commit comments

Comments
 (0)