github.com/companieshouse/lfp-pay-api@v0.0.0-20230203133422-0ca455cd79f9/service/penalties_test.go (about)

     1  package service
     2  
     3  import (
     4  	j "encoding/json"
     5  	"errors"
     6  	"net/http"
     7  	"testing"
     8  
     9  	"github.com/companieshouse/lfp-pay-api-core/models"
    10  	"github.com/companieshouse/lfp-pay-api-core/validators"
    11  	"github.com/companieshouse/lfp-pay-api/e5"
    12  	"github.com/companieshouse/lfp-pay-api/mocks"
    13  	"github.com/golang/mock/gomock"
    14  	"github.com/jarcoal/httpmock"
    15  	. "github.com/smartystreets/goconvey/convey"
    16  )
    17  
    18  var e5ValidationError = `
    19  {
    20    "httpStatusCode" : 400,
    21    "status" : "BAD_REQUEST",
    22    "timestamp" : "2019-07-07T18:40:07Z",
    23    "messageCode" : null,
    24    "message" : "Constraint Validation error",
    25    "debugMessage" : null,
    26    "subErrors" : [ {
    27      "object" : "String",
    28      "field" : "companyCode",
    29      "rejectedValue" : "LPs",
    30      "message" : "size must be between 0 and 2"
    31    } ]
    32  }
    33  `
    34  
    35  func TestUnitMarkTransactionsAsPaid(t *testing.T) {
    36  	Convey("amount must be okay to parse as float", t, func() {
    37  		mockCtrl := gomock.NewController(t)
    38  		defer mockCtrl.Finish()
    39  		mockService := mocks.NewMockService(mockCtrl)
    40  		svc := &PayableResourceService{DAO: mockService}
    41  
    42  		c := &e5.Client{}
    43  		r := models.PayableResource{}
    44  		p := validators.PaymentInformation{Amount: "foo"}
    45  
    46  		err := MarkTransactionsAsPaid(svc, c, r, p)
    47  		So(err, ShouldNotBeNil)
    48  	})
    49  
    50  	Convey("E5 request errors", t, func() {
    51  		httpmock.Activate()
    52  		defer httpmock.DeactivateAndReset()
    53  
    54  		mockCtrl := gomock.NewController(t)
    55  		defer mockCtrl.Finish()
    56  		mockService := mocks.NewMockService(mockCtrl)
    57  		svc := &PayableResourceService{DAO: mockService}
    58  
    59  		Convey("failure in creating a new payment", func() {
    60  			defer httpmock.Reset()
    61  			e5Responder := httpmock.NewStringResponder(http.StatusBadRequest, e5ValidationError)
    62  			httpmock.RegisterResponder(http.MethodPost, "/arTransactions/payment", e5Responder)
    63  
    64  			mockService.EXPECT().SaveE5Error("10000024", "123", e5.CreateAction).Return(errors.New(""))
    65  
    66  			c := &e5.Client{}
    67  			p := validators.PaymentInformation{Amount: "150", PaymentID: "123"}
    68  			r := models.PayableResource{
    69  				Reference:     "123",
    70  				CompanyNumber: "10000024",
    71  				Transactions: []models.TransactionItem{
    72  					{TransactionID: "123", Amount: 150},
    73  				},
    74  			}
    75  
    76  			err := MarkTransactionsAsPaid(svc, c, r, p)
    77  
    78  			So(err, ShouldBeError, e5.ErrE5BadRequest)
    79  		})
    80  
    81  		Convey("failure in authorising a payment", func() {
    82  			defer httpmock.Reset()
    83  			e5Responder := httpmock.NewStringResponder(http.StatusBadRequest, e5ValidationError)
    84  			okResponder := httpmock.NewBytesResponder(http.StatusOK, nil)
    85  			httpmock.RegisterResponder(http.MethodPost, "/arTransactions/payment", okResponder)
    86  			httpmock.RegisterResponder(http.MethodPost, "/arTransactions/payment/authorise", e5Responder)
    87  
    88  			mockService.EXPECT().SaveE5Error("10000024", "123", e5.AuthoriseAction).Return(errors.New(""))
    89  
    90  			c := &e5.Client{}
    91  			p := validators.PaymentInformation{
    92  				Amount:    "150",
    93  				PaymentID: "123",
    94  				CreatedBy: "test@example.com",
    95  			}
    96  
    97  			r := models.PayableResource{
    98  				Reference:     "123",
    99  				CompanyNumber: "10000024",
   100  				Transactions: []models.TransactionItem{
   101  					{TransactionID: "123", Amount: 150},
   102  				},
   103  			}
   104  
   105  			err := MarkTransactionsAsPaid(svc, c, r, p)
   106  
   107  			So(err, ShouldBeError, e5.ErrE5BadRequest)
   108  		})
   109  
   110  		Convey("failure in confirming a payment", func() {
   111  			defer httpmock.Reset()
   112  			e5Responder := httpmock.NewStringResponder(http.StatusBadRequest, e5ValidationError)
   113  			okResponder := httpmock.NewBytesResponder(http.StatusOK, nil)
   114  			httpmock.RegisterResponder(http.MethodPost, "/arTransactions/payment", okResponder)
   115  			httpmock.RegisterResponder(http.MethodPost, "/arTransactions/payment/authorise", okResponder)
   116  			httpmock.RegisterResponder(http.MethodPost, "/arTransactions/payment/confirm", e5Responder)
   117  
   118  			mockService.EXPECT().SaveE5Error("10000024", "123", e5.ConfirmAction).Return(errors.New(""))
   119  
   120  			c := &e5.Client{}
   121  			p := validators.PaymentInformation{
   122  				Amount:    "150",
   123  				PaymentID: "123",
   124  				CreatedBy: "test@example.com",
   125  			}
   126  
   127  			r := models.PayableResource{
   128  				Reference:     "123",
   129  				CompanyNumber: "10000024",
   130  				Transactions: []models.TransactionItem{
   131  					{TransactionID: "123", Amount: 150},
   132  				},
   133  			}
   134  
   135  			err := MarkTransactionsAsPaid(svc, c, r, p)
   136  
   137  			So(err, ShouldBeError, e5.ErrE5BadRequest)
   138  		})
   139  
   140  		Convey("no errors when all 3 calls to E5 succeed", func() {
   141  			defer httpmock.Reset()
   142  			okResponder := httpmock.NewBytesResponder(http.StatusOK, nil)
   143  			httpmock.RegisterResponder(http.MethodPost, "/arTransactions/payment", okResponder)
   144  			httpmock.RegisterResponder(http.MethodPost, "/arTransactions/payment/authorise", okResponder)
   145  			httpmock.RegisterResponder(http.MethodPost, "/arTransactions/payment/confirm", okResponder)
   146  
   147  			c := &e5.Client{}
   148  			p := validators.PaymentInformation{
   149  				Amount:    "150",
   150  				PaymentID: "123",
   151  				CreatedBy: "test@example.com",
   152  			}
   153  
   154  			r := models.PayableResource{
   155  				Reference:     "123",
   156  				CompanyNumber: "10000024",
   157  				Transactions: []models.TransactionItem{
   158  					{TransactionID: "123", Amount: 150},
   159  				},
   160  			}
   161  
   162  			err := MarkTransactionsAsPaid(svc, c, r, p)
   163  
   164  			So(err, ShouldBeNil)
   165  		})
   166  
   167  		Convey("paymentId (PUON) is prefixed with 'X'", func() {
   168  			defer httpmock.Reset()
   169  
   170  			// struct to decode the request body
   171  			type body struct {
   172  				PaymentID string `json:"paymentId"`
   173  			}
   174  
   175  			// check the payment id value before responding.
   176  			paymentIDResponder := func(req *http.Request) (*http.Response, error) {
   177  				resp := httpmock.NewBytesResponse(http.StatusOK, nil)
   178  				defer req.Body.Close()
   179  				var b body
   180  				err := j.NewDecoder(req.Body).Decode(&b)
   181  				if err != nil {
   182  					return nil, errors.New("failed to read request body")
   183  				}
   184  
   185  				if b.PaymentID[0] != 'X' {
   186  					return nil, errors.New("paymentId does not begin with an X")
   187  				}
   188  				return resp, nil
   189  			}
   190  
   191  			httpmock.RegisterResponder(http.MethodPost, "/arTransactions/payment", paymentIDResponder)
   192  			httpmock.RegisterResponder(http.MethodPost, "/arTransactions/payment/authorise", paymentIDResponder)
   193  			httpmock.RegisterResponder(http.MethodPost, "/arTransactions/payment/confirm", paymentIDResponder)
   194  
   195  			c := &e5.Client{}
   196  			p := validators.PaymentInformation{
   197  				Amount:    "150",
   198  				PaymentID: "123",
   199  				CreatedBy: "test@example.com",
   200  			}
   201  
   202  			r := models.PayableResource{
   203  				Reference:     "123",
   204  				CompanyNumber: "10000024",
   205  				Transactions: []models.TransactionItem{
   206  					{TransactionID: "123", Amount: 150},
   207  				},
   208  			}
   209  
   210  			err := MarkTransactionsAsPaid(svc, c, r, p)
   211  			So(err, ShouldBeNil)
   212  
   213  		})
   214  	})
   215  }