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  }