363 lines
8.4 KiB
Go
363 lines
8.4 KiB
Go
package bot
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
storagemodel "github.com/tech/sendico/gateway/tgsettle/storage/model"
|
|
mloggerfactory "github.com/tech/sendico/pkg/mlogger/factory"
|
|
"github.com/tech/sendico/pkg/model"
|
|
)
|
|
|
|
type fakeService struct{}
|
|
|
|
type fakeUserBindingResolver struct {
|
|
bindings map[string]*UserBinding
|
|
err error
|
|
}
|
|
|
|
func (f fakeUserBindingResolver) ResolveUserBinding(_ context.Context, telegramUserID string) (*UserBinding, error) {
|
|
if f.err != nil {
|
|
return nil, f.err
|
|
}
|
|
if f.bindings == nil {
|
|
return nil, nil
|
|
}
|
|
return f.bindings[telegramUserID], nil
|
|
}
|
|
|
|
func (fakeService) ExecutionDelay() time.Duration {
|
|
return 30 * time.Second
|
|
}
|
|
|
|
func (fakeService) MaxPerOperationLimit() string {
|
|
return "1000000"
|
|
}
|
|
|
|
func (fakeService) GetActiveRequestForAccount(context.Context, string) (*storagemodel.TreasuryRequest, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (fakeService) GetAccountProfile(_ context.Context, ledgerAccountID string) (*AccountProfile, error) {
|
|
return &AccountProfile{
|
|
AccountID: ledgerAccountID,
|
|
AccountCode: ledgerAccountID,
|
|
Currency: "USD",
|
|
}, nil
|
|
}
|
|
|
|
func (fakeService) CreateRequest(context.Context, CreateRequestInput) (*storagemodel.TreasuryRequest, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (fakeService) ConfirmRequest(context.Context, string, string) (*storagemodel.TreasuryRequest, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (fakeService) CancelRequest(context.Context, string, string) (*storagemodel.TreasuryRequest, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func TestRouterUnauthorizedInAllowedChatSendsAccessDenied(t *testing.T) {
|
|
var sent []string
|
|
router := NewRouter(
|
|
mloggerfactory.NewLogger(false),
|
|
fakeService{},
|
|
func(_ context.Context, _ string, text string) error {
|
|
sent = append(sent, text)
|
|
return nil
|
|
},
|
|
nil,
|
|
fakeUserBindingResolver{
|
|
bindings: map[string]*UserBinding{
|
|
"123": {
|
|
TelegramUserID: "123",
|
|
LedgerAccountID: "acct-1",
|
|
AllowedChatIDs: []string{"100"},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
handled := router.HandleUpdate(context.Background(), &model.TelegramWebhookUpdate{
|
|
Message: &model.TelegramMessage{
|
|
ChatID: "100",
|
|
FromUserID: "999",
|
|
Text: "/fund",
|
|
},
|
|
})
|
|
if !handled {
|
|
t.Fatalf("expected update to be handled")
|
|
}
|
|
if len(sent) != 1 {
|
|
t.Fatalf("expected one message, got %d", len(sent))
|
|
}
|
|
if sent[0] != unauthorizedMessage {
|
|
t.Fatalf("unexpected message: %q", sent[0])
|
|
}
|
|
}
|
|
|
|
func TestRouterUnknownChatGetsDenied(t *testing.T) {
|
|
var sent []string
|
|
router := NewRouter(
|
|
mloggerfactory.NewLogger(false),
|
|
fakeService{},
|
|
func(_ context.Context, _ string, text string) error {
|
|
sent = append(sent, text)
|
|
return nil
|
|
},
|
|
nil,
|
|
fakeUserBindingResolver{
|
|
bindings: map[string]*UserBinding{
|
|
"123": {
|
|
TelegramUserID: "123",
|
|
LedgerAccountID: "acct-1",
|
|
AllowedChatIDs: []string{"100"},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
handled := router.HandleUpdate(context.Background(), &model.TelegramWebhookUpdate{
|
|
Message: &model.TelegramMessage{
|
|
ChatID: "999",
|
|
FromUserID: "123",
|
|
Text: "/fund",
|
|
},
|
|
})
|
|
if !handled {
|
|
t.Fatalf("expected update to be handled")
|
|
}
|
|
if len(sent) != 1 {
|
|
t.Fatalf("expected one message, got %d", len(sent))
|
|
}
|
|
if sent[0] != unauthorizedChatMessage {
|
|
t.Fatalf("unexpected message: %q", sent[0])
|
|
}
|
|
}
|
|
|
|
func TestRouterEmptyAllowedChats_AllowsAnyChatForAuthorizedUser(t *testing.T) {
|
|
var sent []string
|
|
router := NewRouter(
|
|
mloggerfactory.NewLogger(false),
|
|
fakeService{},
|
|
func(_ context.Context, _ string, text string) error {
|
|
sent = append(sent, text)
|
|
return nil
|
|
},
|
|
nil,
|
|
fakeUserBindingResolver{
|
|
bindings: map[string]*UserBinding{
|
|
"123": {
|
|
TelegramUserID: "123",
|
|
LedgerAccountID: "acct-1",
|
|
},
|
|
},
|
|
},
|
|
)
|
|
handled := router.HandleUpdate(context.Background(), &model.TelegramWebhookUpdate{
|
|
Message: &model.TelegramMessage{
|
|
ChatID: "999",
|
|
FromUserID: "123",
|
|
Text: "/fund",
|
|
},
|
|
})
|
|
if !handled {
|
|
t.Fatalf("expected update to be handled")
|
|
}
|
|
if len(sent) != 1 {
|
|
t.Fatalf("expected one message, got %d", len(sent))
|
|
}
|
|
if sent[0] != amountPromptMessage(
|
|
storagemodel.TreasuryOperationFund,
|
|
&AccountProfile{AccountID: "acct-1", AccountCode: "acct-1", Currency: "USD"},
|
|
"acct-1",
|
|
) {
|
|
t.Fatalf("unexpected message: %q", sent[0])
|
|
}
|
|
}
|
|
|
|
func TestRouterEmptyAllowedChats_UnauthorizedUserGetsDenied(t *testing.T) {
|
|
var sent []string
|
|
router := NewRouter(
|
|
mloggerfactory.NewLogger(false),
|
|
fakeService{},
|
|
func(_ context.Context, _ string, text string) error {
|
|
sent = append(sent, text)
|
|
return nil
|
|
},
|
|
nil,
|
|
fakeUserBindingResolver{
|
|
bindings: map[string]*UserBinding{
|
|
"123": {
|
|
TelegramUserID: "123",
|
|
LedgerAccountID: "acct-1",
|
|
},
|
|
},
|
|
},
|
|
)
|
|
handled := router.HandleUpdate(context.Background(), &model.TelegramWebhookUpdate{
|
|
Message: &model.TelegramMessage{
|
|
ChatID: "777",
|
|
FromUserID: "999",
|
|
Text: "/fund",
|
|
},
|
|
})
|
|
if !handled {
|
|
t.Fatalf("expected update to be handled")
|
|
}
|
|
if len(sent) != 1 {
|
|
t.Fatalf("expected one message, got %d", len(sent))
|
|
}
|
|
if sent[0] != unauthorizedMessage {
|
|
t.Fatalf("unexpected message: %q", sent[0])
|
|
}
|
|
}
|
|
|
|
func TestRouterStartAuthorizedShowsWelcome(t *testing.T) {
|
|
var sent []string
|
|
router := NewRouter(
|
|
mloggerfactory.NewLogger(false),
|
|
fakeService{},
|
|
func(_ context.Context, _ string, text string) error {
|
|
sent = append(sent, text)
|
|
return nil
|
|
},
|
|
nil,
|
|
fakeUserBindingResolver{
|
|
bindings: map[string]*UserBinding{
|
|
"123": {
|
|
TelegramUserID: "123",
|
|
LedgerAccountID: "acct-1",
|
|
},
|
|
},
|
|
},
|
|
)
|
|
handled := router.HandleUpdate(context.Background(), &model.TelegramWebhookUpdate{
|
|
Message: &model.TelegramMessage{
|
|
ChatID: "777",
|
|
FromUserID: "123",
|
|
Text: "/start",
|
|
},
|
|
})
|
|
if !handled {
|
|
t.Fatalf("expected update to be handled")
|
|
}
|
|
if len(sent) != 1 {
|
|
t.Fatalf("expected one message, got %d", len(sent))
|
|
}
|
|
if sent[0] != welcomeMessage(&AccountProfile{AccountID: "acct-1", AccountCode: "acct-1", Currency: "USD"}) {
|
|
t.Fatalf("unexpected message: %q", sent[0])
|
|
}
|
|
}
|
|
|
|
func TestRouterHelpAuthorizedShowsHelp(t *testing.T) {
|
|
var sent []string
|
|
router := NewRouter(
|
|
mloggerfactory.NewLogger(false),
|
|
fakeService{},
|
|
func(_ context.Context, _ string, text string) error {
|
|
sent = append(sent, text)
|
|
return nil
|
|
},
|
|
nil,
|
|
fakeUserBindingResolver{
|
|
bindings: map[string]*UserBinding{
|
|
"123": {
|
|
TelegramUserID: "123",
|
|
LedgerAccountID: "acct-1",
|
|
},
|
|
},
|
|
},
|
|
)
|
|
handled := router.HandleUpdate(context.Background(), &model.TelegramWebhookUpdate{
|
|
Message: &model.TelegramMessage{
|
|
ChatID: "777",
|
|
FromUserID: "123",
|
|
Text: "/help",
|
|
},
|
|
})
|
|
if !handled {
|
|
t.Fatalf("expected update to be handled")
|
|
}
|
|
if len(sent) != 1 {
|
|
t.Fatalf("expected one message, got %d", len(sent))
|
|
}
|
|
if sent[0] != helpMessage("acct-1", "USD") {
|
|
t.Fatalf("unexpected message: %q", sent[0])
|
|
}
|
|
}
|
|
|
|
func TestRouterStartUnauthorizedGetsDenied(t *testing.T) {
|
|
var sent []string
|
|
router := NewRouter(
|
|
mloggerfactory.NewLogger(false),
|
|
fakeService{},
|
|
func(_ context.Context, _ string, text string) error {
|
|
sent = append(sent, text)
|
|
return nil
|
|
},
|
|
nil,
|
|
fakeUserBindingResolver{
|
|
bindings: map[string]*UserBinding{
|
|
"123": {
|
|
TelegramUserID: "123",
|
|
LedgerAccountID: "acct-1",
|
|
},
|
|
},
|
|
},
|
|
)
|
|
handled := router.HandleUpdate(context.Background(), &model.TelegramWebhookUpdate{
|
|
Message: &model.TelegramMessage{
|
|
ChatID: "777",
|
|
FromUserID: "999",
|
|
Text: "/start",
|
|
},
|
|
})
|
|
if !handled {
|
|
t.Fatalf("expected update to be handled")
|
|
}
|
|
if len(sent) != 1 {
|
|
t.Fatalf("expected one message, got %d", len(sent))
|
|
}
|
|
if sent[0] != unauthorizedMessage {
|
|
t.Fatalf("unexpected message: %q", sent[0])
|
|
}
|
|
}
|
|
|
|
func TestRouterPlainTextWithoutSession_ShowsSupportedCommands(t *testing.T) {
|
|
var sent []string
|
|
router := NewRouter(
|
|
mloggerfactory.NewLogger(false),
|
|
fakeService{},
|
|
func(_ context.Context, _ string, text string) error {
|
|
sent = append(sent, text)
|
|
return nil
|
|
},
|
|
nil,
|
|
fakeUserBindingResolver{
|
|
bindings: map[string]*UserBinding{
|
|
"123": {
|
|
TelegramUserID: "123",
|
|
LedgerAccountID: "acct-1",
|
|
},
|
|
},
|
|
},
|
|
)
|
|
handled := router.HandleUpdate(context.Background(), &model.TelegramWebhookUpdate{
|
|
Message: &model.TelegramMessage{
|
|
ChatID: "777",
|
|
FromUserID: "123",
|
|
Text: "hello",
|
|
},
|
|
})
|
|
if !handled {
|
|
t.Fatalf("expected update to be handled")
|
|
}
|
|
if len(sent) != 1 {
|
|
t.Fatalf("expected one message, got %d", len(sent))
|
|
}
|
|
if sent[0] != supportedCommandsMessage() {
|
|
t.Fatalf("unexpected message: %q", sent[0])
|
|
}
|
|
}
|