mirror of
https://github.com/larksuite/cli.git
synced 2026-07-06 08:12:36 +08:00
136 lines
4.9 KiB
Go
136 lines
4.9 KiB
Go
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package mail
|
|
|
|
import (
|
|
"bytes"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/zalando/go-keyring"
|
|
|
|
"github.com/larksuite/cli/internal/auth"
|
|
"github.com/larksuite/cli/internal/cmdutil"
|
|
"github.com/larksuite/cli/internal/httpmock"
|
|
)
|
|
|
|
// mailShortcutTestFactoryWithSendScope mirrors mailShortcutTestFactory but
|
|
// additionally grants the mail:user_mailbox.message:send scope so tests can
|
|
// exercise code paths guarded by validateConfirmSendScope (e.g. validateSendTime).
|
|
func mailShortcutTestFactoryWithSendScope(t *testing.T) (*cmdutil.Factory, *bytes.Buffer, *bytes.Buffer, *httpmock.Registry) {
|
|
t.Helper()
|
|
keyring.MockInit()
|
|
t.Setenv("HOME", t.TempDir())
|
|
|
|
cfg := mailTestConfig()
|
|
token := &auth.StoredUAToken{
|
|
UserOpenId: cfg.UserOpenId,
|
|
AppId: cfg.AppID,
|
|
AccessToken: "test-user-access-token",
|
|
RefreshToken: "test-refresh-token",
|
|
ExpiresAt: time.Now().Add(1 * time.Hour).UnixMilli(),
|
|
RefreshExpiresAt: time.Now().Add(24 * time.Hour).UnixMilli(),
|
|
Scope: "mail:user_mailbox.messages:write mail:user_mailbox.messages:read mail:user_mailbox.message:modify mail:user_mailbox.message:send mail:user_mailbox.message:readonly mail:user_mailbox.message.address:read mail:user_mailbox.message.subject:read mail:user_mailbox.message.body:read mail:user_mailbox:readonly",
|
|
GrantedAt: time.Now().Add(-1 * time.Hour).UnixMilli(),
|
|
}
|
|
if err := auth.SetStoredToken(token); err != nil {
|
|
t.Fatalf("SetStoredToken() error = %v", err)
|
|
}
|
|
t.Cleanup(func() {
|
|
_ = auth.RemoveStoredToken(cfg.AppID, cfg.UserOpenId)
|
|
})
|
|
return cmdutil.TestFactory(t, cfg)
|
|
}
|
|
|
|
// tooSoonSendTime returns a send-time 60s in the future — below the 5-minute
|
|
// floor enforced by validateSendTime.
|
|
func tooSoonSendTime() string {
|
|
return strconv.FormatInt(time.Now().Unix()+60, 10)
|
|
}
|
|
|
|
// futureSendTime returns a send-time 10 minutes in the future — above the floor.
|
|
func futureSendTime() string {
|
|
return strconv.FormatInt(time.Now().Unix()+10*60, 10)
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Invalid --send-time rejected by each compose shortcut
|
|
// ---------------------------------------------------------------------------
|
|
|
|
func TestMailSend_SendTimeTooSoon(t *testing.T) {
|
|
f, stdout, _, _ := mailShortcutTestFactoryWithSendScope(t)
|
|
err := runMountedMailShortcut(t, MailSend, []string{
|
|
"+send", "--to", "alice@example.com", "--subject", "hi", "--body", "hello",
|
|
"--confirm-send", "--send-time", tooSoonSendTime(),
|
|
}, f, stdout)
|
|
if err == nil {
|
|
t.Fatal("expected error for too-soon send-time, got nil")
|
|
}
|
|
if !strings.Contains(err.Error(), "5 minutes") {
|
|
t.Errorf("expected 5-minute error, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestMailReply_SendTimeTooSoon(t *testing.T) {
|
|
f, stdout, _, _ := mailShortcutTestFactoryWithSendScope(t)
|
|
err := runMountedMailShortcut(t, MailReply, []string{
|
|
"+reply", "--message-id", "msg_001", "--body", "hello",
|
|
"--confirm-send", "--send-time", tooSoonSendTime(),
|
|
}, f, stdout)
|
|
if err == nil {
|
|
t.Fatal("expected error for too-soon send-time, got nil")
|
|
}
|
|
if !strings.Contains(err.Error(), "5 minutes") {
|
|
t.Errorf("expected 5-minute error, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestMailReplyAll_SendTimeTooSoon(t *testing.T) {
|
|
f, stdout, _, _ := mailShortcutTestFactoryWithSendScope(t)
|
|
err := runMountedMailShortcut(t, MailReplyAll, []string{
|
|
"+reply-all", "--message-id", "msg_001", "--body", "hello",
|
|
"--confirm-send", "--send-time", tooSoonSendTime(),
|
|
}, f, stdout)
|
|
if err == nil {
|
|
t.Fatal("expected error for too-soon send-time, got nil")
|
|
}
|
|
if !strings.Contains(err.Error(), "5 minutes") {
|
|
t.Errorf("expected 5-minute error, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestMailForward_SendTimeTooSoon(t *testing.T) {
|
|
f, stdout, _, _ := mailShortcutTestFactoryWithSendScope(t)
|
|
err := runMountedMailShortcut(t, MailForward, []string{
|
|
"+forward", "--message-id", "msg_001", "--to", "alice@example.com",
|
|
"--confirm-send", "--send-time", tooSoonSendTime(),
|
|
}, f, stdout)
|
|
if err == nil {
|
|
t.Fatal("expected error for too-soon send-time, got nil")
|
|
}
|
|
if !strings.Contains(err.Error(), "5 minutes") {
|
|
t.Errorf("expected 5-minute error, got: %v", err)
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// --send-time without --confirm-send is rejected up front
|
|
// ---------------------------------------------------------------------------
|
|
|
|
func TestMailSend_SendTimeWithoutConfirmSend(t *testing.T) {
|
|
f, stdout, _, _ := mailShortcutTestFactoryWithSendScope(t)
|
|
err := runMountedMailShortcut(t, MailSend, []string{
|
|
"+send", "--to", "alice@example.com", "--subject", "hi", "--body", "hello",
|
|
"--send-time", futureSendTime(),
|
|
}, f, stdout)
|
|
if err == nil {
|
|
t.Fatal("expected error for --send-time without --confirm-send, got nil")
|
|
}
|
|
if !strings.Contains(err.Error(), "--confirm-send") {
|
|
t.Errorf("expected error to mention --confirm-send, got: %v", err)
|
|
}
|
|
}
|