flamingo.me/flamingo-commerce/v3@v3.11.0/checkout/domain/placeorder/states/create_payment_test.go (about) 1 package states_test 2 3 import ( 4 "context" 5 "errors" 6 "net/url" 7 "testing" 8 9 "github.com/stretchr/testify/assert" 10 "github.com/stretchr/testify/mock" 11 "github.com/stretchr/testify/require" 12 13 cartDomain "flamingo.me/flamingo-commerce/v3/cart/domain/cart" 14 "flamingo.me/flamingo-commerce/v3/cart/domain/placeorder" 15 "flamingo.me/flamingo-commerce/v3/checkout/domain/placeorder/process" 16 "flamingo.me/flamingo-commerce/v3/checkout/domain/placeorder/states" 17 "flamingo.me/flamingo-commerce/v3/payment/application" 18 "flamingo.me/flamingo-commerce/v3/payment/domain" 19 "flamingo.me/flamingo-commerce/v3/payment/interfaces" 20 "flamingo.me/flamingo-commerce/v3/payment/interfaces/mocks" 21 price "flamingo.me/flamingo-commerce/v3/price/domain" 22 ) 23 24 type rawTransactionData struct{} 25 26 func TestCreatePayment_Run(t *testing.T) { 27 t.Run("happy path", func(t *testing.T) { 28 factory := provideProcessFactory(t) 29 30 cart := provideCartWithPaymentSelection(t) 31 p, _ := factory.New(&url.URL{}, cart) 32 33 state := states.CreatePayment{} 34 35 expectedPayment := &placeorder.Payment{Gateway: "test", RawTransactionData: &rawTransactionData{}} 36 gateway := mocks.NewWebCartPaymentGateway(t) 37 gateway.EXPECT().StartFlow(mock.Anything, mock.Anything, p.Context().UUID, p.Context().ReturnURL).Return(&domain.FlowResult{EarlyPlaceOrder: true}, nil).Once() 38 gateway.EXPECT().OrderPaymentFromFlow(mock.Anything, mock.Anything, p.Context().UUID).Return(expectedPayment, nil).Once() 39 paymentService := paymentServiceHelper(t, gateway) 40 41 state.Inject(paymentService) 42 43 expectedResult := process.RunResult{ 44 RollbackData: states.CreatePaymentRollbackData{ 45 Gateway: expectedPayment.Gateway, 46 PaymentID: expectedPayment.PaymentID, 47 RawTransactionData: &rawTransactionData{}, 48 }, 49 } 50 result := state.Run(context.Background(), p) 51 assert.Equal(t, result, expectedResult) 52 assert.Equal(t, p.Context().CurrentStateName, states.CompleteCart{}.Name()) 53 gateway.AssertExpectations(t) 54 }) 55 56 t.Run("error missing payment selection", func(t *testing.T) { 57 factory := provideProcessFactory(t) 58 59 cart := cartDomain.Cart{} 60 61 p, _ := factory.New(&url.URL{}, cart) 62 63 state := states.CreatePayment{} 64 65 paymentService := paymentServiceHelper(t, nil) 66 67 state.Inject(paymentService) 68 69 result := state.Run(context.Background(), p) 70 assert.NotNil(t, result.Failed, "Missing PaymentSelection in cart should lead to an error") 71 }) 72 73 t.Run("error during gateway.StartFlow", func(t *testing.T) { 74 factory := provideProcessFactory(t) 75 76 cart := provideCartWithPaymentSelection(t) 77 78 p, _ := factory.New(&url.URL{}, cart) 79 80 state := states.CreatePayment{} 81 82 expectedError := errors.New("StartFlow payment error") 83 84 gateway := mocks.NewWebCartPaymentGateway(t) 85 gateway.EXPECT().StartFlow(mock.Anything, mock.Anything, p.Context().UUID, p.Context().ReturnURL).Return(nil, expectedError).Once() 86 paymentService := paymentServiceHelper(t, gateway) 87 state.Inject(paymentService) 88 89 expectedResult := process.RunResult{ 90 Failed: process.PaymentErrorOccurredReason{Error: expectedError.Error()}, 91 } 92 assert.Equal(t, state.Run(context.Background(), p), expectedResult) 93 gateway.AssertExpectations(t) 94 }) 95 96 t.Run("error during gateway.OrderPaymentFromFlow", func(t *testing.T) { 97 factory := provideProcessFactory(t) 98 99 cart := provideCartWithPaymentSelection(t) 100 101 p, _ := factory.New(&url.URL{}, cart) 102 103 state := states.CreatePayment{} 104 105 expectedError := errors.New("OrderPaymentFromFlow payment error") 106 107 gateway := mocks.NewWebCartPaymentGateway(t) 108 gateway.EXPECT().StartFlow(mock.Anything, mock.Anything, p.Context().UUID, p.Context().ReturnURL).Return(&domain.FlowResult{}, nil).Once() 109 gateway.EXPECT().OrderPaymentFromFlow(mock.Anything, mock.Anything, p.Context().UUID).Return(nil, expectedError).Once() 110 111 paymentService := paymentServiceHelper(t, gateway) 112 state.Inject(paymentService) 113 114 expectedResult := process.RunResult{ 115 Failed: process.PaymentErrorOccurredReason{Error: expectedError.Error()}, 116 } 117 assert.Equal(t, state.Run(context.Background(), p), expectedResult) 118 gateway.AssertExpectations(t) 119 }) 120 } 121 122 func provideProcessFactory(t *testing.T) *process.Factory { 123 t.Helper() 124 factory := &process.Factory{} 125 factory.Inject( 126 func() *process.Process { 127 return &process.Process{} 128 }, 129 &struct { 130 StartState process.State `inject:"startState"` 131 FailedState process.State `inject:"failedState"` 132 }{ 133 StartState: &states.New{}, 134 }, 135 ) 136 return factory 137 } 138 139 func provideCartWithPaymentSelection(t *testing.T) cartDomain.Cart { 140 t.Helper() 141 cart := cartDomain.Cart{} 142 paymentSelection, err := cartDomain.NewDefaultPaymentSelection("test", map[string]string{price.ChargeTypeMain: "main"}, cart) 143 require.NoError(t, err) 144 cart.PaymentSelection = paymentSelection 145 return cart 146 } 147 148 func paymentServiceHelper(t *testing.T, gateway interfaces.WebCartPaymentGateway) *application.PaymentService { 149 t.Helper() 150 paymentService := &application.PaymentService{} 151 152 paymentService.Inject(func() map[string]interfaces.WebCartPaymentGateway { 153 return map[string]interfaces.WebCartPaymentGateway{ 154 "test": gateway, 155 } 156 }) 157 return paymentService 158 } 159 160 func TestCreatePayment_IsFinal(t *testing.T) { 161 state := states.CreatePayment{} 162 assert.False(t, state.IsFinal()) 163 } 164 165 func TestCreatePayment_Rollback(t *testing.T) { 166 t.Run("happy path", func(t *testing.T) { 167 state := states.CreatePayment{} 168 169 var data interface{} 170 171 payment := &placeorder.Payment{ 172 Gateway: "test", 173 Transactions: nil, 174 RawTransactionData: &rawTransactionData{}, 175 PaymentID: "1234", 176 } 177 178 data = states.CreatePaymentRollbackData{ 179 Gateway: payment.Gateway, 180 PaymentID: payment.PaymentID, 181 RawTransactionData: payment.RawTransactionData, 182 } 183 184 gateway := mocks.NewWebCartPaymentGateway(t) 185 gateway.EXPECT().CancelOrderPayment(mock.Anything, payment).Return(nil).Once() 186 paymentService := paymentServiceHelper(t, gateway) 187 state.Inject(paymentService) 188 189 result := state.Rollback(context.Background(), data) 190 assert.Nil(t, result) 191 gateway.AssertExpectations(t) 192 }) 193 194 t.Run("RollbackData not of type", func(t *testing.T) { 195 state := states.CreatePayment{} 196 197 assert.Error(t, state.Rollback(context.Background(), "string")) 198 }) 199 200 t.Run("Error during payment selection", func(t *testing.T) { 201 state := states.CreatePayment{} 202 203 var data interface{} 204 205 payment := &placeorder.Payment{ 206 Gateway: "non-existing", 207 RawTransactionData: &rawTransactionData{}, 208 } 209 210 data = states.CreatePaymentRollbackData{ 211 Gateway: payment.Gateway, PaymentID: payment.PaymentID, RawTransactionData: payment.RawTransactionData} 212 213 paymentService := paymentServiceHelper(t, nil) 214 state.Inject(paymentService) 215 assert.Error(t, state.Rollback(context.Background(), data), "Missing payment selection / gateway should lead to an error") 216 }) 217 218 t.Run("Error during CancelOrderPayment", func(t *testing.T) { 219 state := states.CreatePayment{} 220 221 var data interface{} 222 223 payment := &placeorder.Payment{ 224 Gateway: "test", 225 Transactions: nil, 226 RawTransactionData: &rawTransactionData{}, 227 PaymentID: "1234", 228 } 229 230 data = states.CreatePaymentRollbackData{ 231 Gateway: payment.Gateway, 232 PaymentID: payment.PaymentID, 233 RawTransactionData: payment.RawTransactionData, 234 } 235 236 expectedError := errors.New("generic payment error") 237 gateway := mocks.NewWebCartPaymentGateway(t) 238 gateway.EXPECT().CancelOrderPayment(mock.Anything, payment).Return(expectedError).Once() 239 paymentService := paymentServiceHelper(t, gateway) 240 state.Inject(paymentService) 241 assert.EqualError(t, state.Rollback(context.Background(), data), expectedError.Error()) 242 gateway.AssertExpectations(t) 243 }) 244 245 }