github.com/companieshouse/lfp-pay-api@v0.0.0-20230203133422-0ca455cd79f9/e5/client_test.go (about) 1 package e5 2 3 import ( 4 "net/http" 5 "testing" 6 7 "github.com/jarcoal/httpmock" 8 . "github.com/smartystreets/goconvey/convey" 9 "gopkg.in/go-playground/validator.v9" 10 ) 11 12 func hasFieldError(field, tag string, errs validator.ValidationErrors) bool { 13 for _, e := range errs { 14 f := e.Field() 15 t := e.Tag() 16 if f == field && t == tag { 17 return true 18 } 19 } 20 return false 21 } 22 23 func TestUnitClient_CreatePayment(t *testing.T) { 24 e5 := NewClient("foo", "https://e5") 25 url := "https://e5/arTransactions/payment?ADV_userName=foo" 26 27 Convey("creating a payment", t, func() { 28 input := &CreatePaymentInput{ 29 CompanyCode: "LP", 30 CompanyNumber: "1000024", 31 PaymentID: "1234", 32 TotalValue: 100, 33 Transactions: []*CreatePaymentTransaction{ 34 { 35 Reference: "1234", 36 Value: 100, 37 }, 38 }, 39 } 40 41 Convey("response should be unsuccessful when there is a 500 error from E5", func() { 42 httpmock.Activate() 43 defer httpmock.DeactivateAndReset() 44 45 httpErr := &apiErrorResponse{Code: 500, Message: "test error"} 46 responder, _ := httpmock.NewJsonResponder(http.StatusInternalServerError, httpErr) 47 httpmock.RegisterResponder(http.MethodPost, url, responder) 48 49 err := e5.CreatePayment(input) 50 51 So(err, ShouldBeError, ErrE5InternalServer) 52 }) 53 54 Convey("response should be unsuccessful when the company does not exist", func() { 55 httpmock.Activate() 56 defer httpmock.DeactivateAndReset() 57 58 httpErr := &apiErrorResponse{Code: 404, Message: "company not found"} 59 responder, _ := httpmock.NewJsonResponder(http.StatusNotFound, httpErr) 60 httpmock.RegisterResponder(http.MethodPost, url, responder) 61 62 err := e5.CreatePayment(input) 63 64 So(err, ShouldBeError, ErrE5NotFound) 65 }) 66 67 Convey("response should be successful if a 200 is returned from E5", func() { 68 httpmock.Activate() 69 defer httpmock.DeactivateAndReset() 70 71 responder := httpmock.NewBytesResponder(http.StatusOK, nil) 72 httpmock.RegisterResponder(http.MethodPost, url, responder) 73 74 err := e5.CreatePayment(input) 75 76 So(err, ShouldBeNil) 77 }) 78 }) 79 } 80 81 // this is the response returned by e5 when the company number is incorrect i.e. no transactions exist 82 var e5EmptyResponse = ` 83 { 84 "page" : { 85 "size" : 0, 86 "totalElements" : 0, 87 "totalPages" : 1, 88 "number" : 0 89 }, 90 "data" : [ ] 91 }` 92 93 var e5TransactionResponse = ` 94 { 95 "page" : { 96 "size" : 1, 97 "totalElements" : 1, 98 "totalPages" : 1, 99 "number" : 0 100 }, 101 "data" : [ { 102 "companyCode" : "LP", 103 "ledgerCode" : "EW", 104 "customerCode" : "10000024", 105 "transactionReference" : "00378420", 106 "transactionDate" : "2017-11-28", 107 "madeUpDate" : "2017-02-28", 108 "amount" : 150, 109 "outstandingAmount" : 150, 110 "isPaid" : false, 111 "transactionType" : "1", 112 "transactionSubType" : "EU", 113 "typeDescription" : "Penalty Ltd Wel & Eng <=1m LTDWA ", 114 "dueDate" : "2017-12-12" 115 }] 116 } 117 ` 118 119 var e5ValidationError = ` 120 { 121 "httpStatusCode" : 400, 122 "status" : "BAD_REQUEST", 123 "timestamp" : "2019-07-07T18:40:07Z", 124 "messageCode" : null, 125 "message" : "Constraint Validation error", 126 "debugMessage" : null, 127 "subErrors" : [ { 128 "object" : "String", 129 "field" : "companyCode", 130 "rejectedValue" : "LPs", 131 "message" : "size must be between 0 and 2" 132 } ] 133 } 134 ` 135 136 func TestUnitClient_GetTransactions(t *testing.T) { 137 Convey("getting a list of transactions for a company", t, func() { 138 e5 := NewClient("foo", "https://e5") 139 url := "https://e5/arTransactions/10000024?ADV_userName=foo&companyCode=LP&fromDate=1990-01-01" 140 141 Convey("company does not exist or no transactions returned", func() { 142 httpmock.Activate() 143 defer httpmock.DeactivateAndReset() 144 145 responder := httpmock.NewStringResponder(http.StatusOK, e5EmptyResponse) 146 httpmock.RegisterResponder(http.MethodGet, url, responder) 147 148 r, err := e5.GetTransactions(&GetTransactionsInput{CompanyNumber: "10000024", CompanyCode: "LP"}) 149 150 So(err, ShouldBeNil) 151 So(r.Transactions, ShouldBeEmpty) 152 So(r.Page.Size, ShouldEqual, 0) 153 }) 154 155 Convey("should return a list of transactions", func() { 156 httpmock.Activate() 157 defer httpmock.DeactivateAndReset() 158 159 responder := httpmock.NewStringResponder(http.StatusOK, e5TransactionResponse) 160 httpmock.RegisterResponder(http.MethodGet, url, responder) 161 162 r, err := e5.GetTransactions(&GetTransactionsInput{CompanyNumber: "10000024", CompanyCode: "LP"}) 163 164 So(err, ShouldBeNil) 165 So(r.Transactions, ShouldHaveLength, 1) 166 }) 167 168 Convey("using an incorrect company code", func() { 169 httpmock.Activate() 170 defer httpmock.DeactivateAndReset() 171 172 responder := httpmock.NewStringResponder(http.StatusBadRequest, e5ValidationError) 173 httpmock.RegisterResponder(http.MethodGet, url, responder) 174 175 r, err := e5.GetTransactions(&GetTransactionsInput{CompanyNumber: "10000024", CompanyCode: "LP"}) 176 177 So(r, ShouldBeNil) 178 So(err, ShouldBeError, ErrE5BadRequest) 179 }) 180 181 }) 182 } 183 184 func TestUnitClient_AuthorisePayment(t *testing.T) { 185 e5 := NewClient("foo", "https://e5") 186 url := "https://e5/arTransactions/payment/authorise?ADV_userName=foo" 187 188 Convey("email, paymentId are required parameters", t, func() { 189 input := &AuthorisePaymentInput{} 190 191 err := e5.AuthorisePayment(input) 192 193 So(err, ShouldNotBeNil) 194 195 errors := err.(validator.ValidationErrors) 196 197 So(errors, ShouldHaveLength, 3) 198 So(hasFieldError("Email", "required", errors), ShouldBeTrue) 199 So(hasFieldError("PaymentID", "required", errors), ShouldBeTrue) 200 So(hasFieldError("CompanyCode", "required", errors), ShouldBeTrue) 201 }) 202 203 Convey("500 error from E5", t, func() { 204 httpmock.Activate() 205 defer httpmock.DeactivateAndReset() 206 207 responder := httpmock.NewStringResponder(http.StatusInternalServerError, e5ValidationError) 208 httpmock.RegisterResponder(http.MethodPost, url, responder) 209 210 err := e5.AuthorisePayment(&AuthorisePaymentInput{PaymentID: "123", Email: "test@example.com", CompanyCode: "LP"}) 211 212 So(err, ShouldBeError, ErrE5InternalServer) 213 }) 214 215 Convey("400 error from E5", t, func() { 216 httpmock.Activate() 217 defer httpmock.DeactivateAndReset() 218 219 responder := httpmock.NewStringResponder(http.StatusBadRequest, e5ValidationError) 220 httpmock.RegisterResponder(http.MethodPost, url, responder) 221 222 err := e5.AuthorisePayment(&AuthorisePaymentInput{PaymentID: "123", Email: "test@example.com", CompanyCode: "LP"}) 223 224 So(err, ShouldBeError, ErrE5BadRequest) 225 }) 226 227 Convey("404 error from E5", t, func() { 228 httpmock.Activate() 229 defer httpmock.DeactivateAndReset() 230 231 responder := httpmock.NewStringResponder(http.StatusNotFound, e5ValidationError) 232 httpmock.RegisterResponder(http.MethodPost, url, responder) 233 234 err := e5.AuthorisePayment(&AuthorisePaymentInput{PaymentID: "123", Email: "test@example.com", CompanyCode: "LP"}) 235 236 So(err, ShouldBeError, ErrE5NotFound) 237 }) 238 239 Convey("403 error from E5", t, func() { 240 httpmock.Activate() 241 defer httpmock.DeactivateAndReset() 242 243 responder := httpmock.NewStringResponder(http.StatusForbidden, e5ValidationError) 244 httpmock.RegisterResponder(http.MethodPost, url, responder) 245 246 err := e5.AuthorisePayment(&AuthorisePaymentInput{PaymentID: "123", Email: "test@example.com", CompanyCode: "LP"}) 247 248 So(err, ShouldBeError, ErrUnexpectedServerError) 249 }) 250 251 Convey("everything okay when there are not errors", t, func() { 252 httpmock.Activate() 253 defer httpmock.DeactivateAndReset() 254 255 responder := httpmock.NewStringResponder(http.StatusOK, "") 256 httpmock.RegisterResponder(http.MethodPost, url, responder) 257 258 input := &AuthorisePaymentInput{PaymentID: "123", Email: "test@example.com", CompanyCode: "LP"} 259 err := e5.AuthorisePayment(input) 260 261 So(err, ShouldBeNil) 262 }) 263 } 264 265 func TestUnitClient_Confirm(t *testing.T) { 266 e5 := NewClient("foo", "https://e5") 267 url := "https://e5/arTransactions/payment/confirm?ADV_userName=foo" 268 input := &PaymentActionInput{PaymentID: "123", CompanyCode: "LP"} 269 270 Convey("paymentId is required", t, func() { 271 err := e5.ConfirmPayment(&PaymentActionInput{}) 272 273 errors := err.(validator.ValidationErrors) 274 275 So(err, ShouldNotBeNil) 276 So(hasFieldError("PaymentID", "required", errors), ShouldBeTrue) 277 }) 278 279 Convey("500 error from E5", t, func() { 280 httpmock.Activate() 281 defer httpmock.DeactivateAndReset() 282 283 responder := httpmock.NewStringResponder(http.StatusInternalServerError, e5ValidationError) 284 httpmock.RegisterResponder(http.MethodPost, url, responder) 285 286 err := e5.ConfirmPayment(input) 287 288 So(err, ShouldBeError, ErrE5InternalServer) 289 }) 290 291 Convey("400 error from E5", t, func() { 292 httpmock.Activate() 293 defer httpmock.DeactivateAndReset() 294 295 responder := httpmock.NewStringResponder(http.StatusBadRequest, e5ValidationError) 296 httpmock.RegisterResponder(http.MethodPost, url, responder) 297 298 err := e5.ConfirmPayment(input) 299 300 So(err, ShouldBeError, ErrE5BadRequest) 301 }) 302 303 Convey("404 error from E5", t, func() { 304 httpmock.Activate() 305 defer httpmock.DeactivateAndReset() 306 307 responder := httpmock.NewStringResponder(http.StatusNotFound, e5ValidationError) 308 httpmock.RegisterResponder(http.MethodPost, url, responder) 309 310 err := e5.ConfirmPayment(input) 311 312 So(err, ShouldBeError, ErrE5NotFound) 313 }) 314 315 Convey("403 error from E5", t, func() { 316 httpmock.Activate() 317 defer httpmock.DeactivateAndReset() 318 319 responder := httpmock.NewStringResponder(http.StatusForbidden, e5ValidationError) 320 httpmock.RegisterResponder(http.MethodPost, url, responder) 321 322 err := e5.ConfirmPayment(input) 323 324 So(err, ShouldBeError, ErrUnexpectedServerError) 325 }) 326 327 Convey("successful confirmation", t, func() { 328 httpmock.Activate() 329 defer httpmock.DeactivateAndReset() 330 331 responder := httpmock.NewStringResponder(http.StatusOK, "") 332 httpmock.RegisterResponder(http.MethodPost, url, responder) 333 334 err := e5.ConfirmPayment(input) 335 336 So(err, ShouldBeNil) 337 }) 338 }