mirror of
https://github.com/hanzo-fi/payments.git
synced 2026-10-30 20:31:20 +00:00
108 lines
3.7 KiB
Go
108 lines
3.7 KiB
Go
package routable
|
|
|
|
import (
|
|
"errors"
|
|
"math/big"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/hanzo-fi/go-libs/v5/pkg/observe/log"
|
|
"github.com/hanzo-fi/payments/ee/plugins/routable/client"
|
|
"github.com/hanzo-fi/payments/pkg/domain/plugins"
|
|
"github.com/hanzo-fi/payments/pkg/domain/models"
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
"go.uber.org/mock/gomock"
|
|
)
|
|
|
|
var _ = Describe("Routable createTransfer", func() {
|
|
var (
|
|
ctrl *gomock.Controller
|
|
mock *client.MockClient
|
|
plg *Plugin
|
|
logger = logging.NewDefaultLogger(GinkgoWriter, true, false, false)
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
ctrl = gomock.NewController(GinkgoT())
|
|
mock = client.NewMockClient(ctrl)
|
|
plg = &Plugin{
|
|
Plugin: plugins.NewBasePlugin(),
|
|
name: "routable",
|
|
logger: logger,
|
|
client: mock,
|
|
config: Config{ActingTeamMember: "tm_default"},
|
|
}
|
|
})
|
|
|
|
AfterEach(func() {
|
|
ctrl.Finish()
|
|
})
|
|
|
|
pi := func() models.PSPPaymentInitiation {
|
|
return models.PSPPaymentInitiation{
|
|
Reference: "pi_2",
|
|
CreatedAt: time.Now().UTC(),
|
|
Amount: big.NewInt(5000), // 50.00 USD
|
|
Asset: "USD/2",
|
|
SourceAccount: &models.PSPAccount{Reference: "acc_1"},
|
|
DestinationAccount: &models.PSPAccount{Reference: "co_1"},
|
|
}
|
|
}
|
|
|
|
It("marks the response Payment as TRANSFER even though the rail is a Routable payable", func(ctx SpecContext) {
|
|
mock.EXPECT().CreatePayable(gomock.Any(), gomock.Any()).Return(
|
|
&client.Payable{ID: "pa_t", Status: "completed", Amount: "50.00", CurrencyCode: "USD", CreatedAt: time.Now().UTC()},
|
|
http.StatusCreated,
|
|
nil,
|
|
)
|
|
resp, err := plg.createTransfer(ctx, models.CreateTransferRequest{PaymentInitiation: pi()})
|
|
Expect(err).To(BeNil())
|
|
Expect(resp.Payment).NotTo(BeNil())
|
|
Expect(resp.Payment.Type).To(Equal(models.PAYMENT_TYPE_TRANSFER))
|
|
})
|
|
|
|
It("returns PollingTransferID for sync 201 responses with a non-terminal status", func(ctx SpecContext) {
|
|
mock.EXPECT().CreatePayable(gomock.Any(), gomock.Any()).Return(
|
|
&client.Payable{ID: "pa_t2", Status: "pending", Amount: "50.00", CurrencyCode: "USD", CreatedAt: time.Now().UTC()},
|
|
http.StatusCreated,
|
|
nil,
|
|
)
|
|
resp, err := plg.createTransfer(ctx, models.CreateTransferRequest{PaymentInitiation: pi()})
|
|
Expect(err).To(BeNil())
|
|
Expect(resp.Payment).To(BeNil())
|
|
Expect(resp.PollingTransferID).NotTo(BeNil())
|
|
Expect(*resp.PollingTransferID).To(Equal("pa_t2"))
|
|
})
|
|
|
|
// Same ErrInvalidRequest wrapping contract as createPayout (shared
|
|
// initiatePayable choke point).
|
|
It("wraps validation errors with ErrInvalidRequest on createTransfer", func(ctx SpecContext) {
|
|
bad := pi()
|
|
bad.SourceAccount = nil
|
|
_, err := plg.createTransfer(ctx, models.CreateTransferRequest{PaymentInitiation: bad})
|
|
Expect(errors.Is(err, models.ErrInvalidRequest)).To(BeTrue())
|
|
|
|
bad = pi()
|
|
bad.DestinationAccount = nil
|
|
_, err = plg.createTransfer(ctx, models.CreateTransferRequest{PaymentInitiation: bad})
|
|
Expect(errors.Is(err, models.ErrInvalidRequest)).To(BeTrue())
|
|
})
|
|
|
|
// Async 202 path: Routable echoes only {id}. The plugin must return
|
|
// PollingTransferID without trying to map the half-empty payable
|
|
// (which would error out on the missing currency / amount).
|
|
It("returns PollingTransferID for async 202 responses with no mapping attempted", func(ctx SpecContext) {
|
|
mock.EXPECT().CreatePayable(gomock.Any(), gomock.Any()).Return(
|
|
&client.Payable{ID: "pa_t3"}, // 202 body: just {id}, no amount/currency
|
|
http.StatusAccepted,
|
|
nil,
|
|
)
|
|
resp, err := plg.createTransfer(ctx, models.CreateTransferRequest{PaymentInitiation: pi()})
|
|
Expect(err).To(BeNil(), "must NOT error on the missing currency in a 202 body")
|
|
Expect(resp.Payment).To(BeNil())
|
|
Expect(resp.PollingTransferID).NotTo(BeNil())
|
|
Expect(*resp.PollingTransferID).To(Equal("pa_t3"))
|
|
})
|
|
})
|