github.com/companieshouse/insolvency-api@v0.0.0-20231024103413-440c973d9e9b/handlers/progress_report_resource_test.go (about)

     1  package handlers
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"net/http"
     8  	"net/http/httptest"
     9  	"os"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/companieshouse/chs.go/log"
    14  	"github.com/companieshouse/insolvency-api/dao"
    15  	"github.com/companieshouse/insolvency-api/mocks"
    16  	mock_dao "github.com/companieshouse/insolvency-api/mocks"
    17  	"github.com/companieshouse/insolvency-api/models"
    18  	"github.com/companieshouse/insolvency-api/utils"
    19  	"github.com/golang/mock/gomock"
    20  	"github.com/gorilla/mux"
    21  	"github.com/jarcoal/httpmock"
    22  	. "github.com/smartystreets/goconvey/convey"
    23  )
    24  
    25  func serveHandleCreateProgressReport(body []byte, service dao.Service, helperService utils.HelperService, tranIDSet bool, res *httptest.ResponseRecorder) *httptest.ResponseRecorder {
    26  	path := "/transactions/123456789/insolvency/progress-report"
    27  	req := httptest.NewRequest(http.MethodPost, path, bytes.NewReader(body))
    28  	if tranIDSet {
    29  		req = mux.SetURLVars(req, map[string]string{"transaction_id": transactionID})
    30  	}
    31  
    32  	handler := HandleCreateProgressReport(service, helperService)
    33  	handler.ServeHTTP(res, req)
    34  
    35  	return res
    36  }
    37  
    38  func TestUnitHandleCreateProgressReport(t *testing.T) {
    39  	err := os.Chdir("..")
    40  	if err != nil {
    41  		log.ErrorR(nil, fmt.Errorf("error accessing root directory"))
    42  	}
    43  
    44  	helperService := utils.NewHelperService()
    45  
    46  	Convey("Must need a transaction ID in the url", t, func() {
    47  		mockService, _, rec := mocks.CreateTestObjects(t)
    48  
    49  		body, _ := json.Marshal(&models.InsolvencyRequest{})
    50  
    51  		res := serveHandleCreateProgressReport(body, mockService, helperService, false, rec)
    52  
    53  		So(res.Code, ShouldEqual, http.StatusBadRequest)
    54  		So(res.Body.String(), ShouldContainSubstring, "transaction ID is not in the URL path")
    55  	})
    56  
    57  	Convey("Error checking if transaction is closed against transaction api", t, func() {
    58  		mockService, _, rec := mocks.CreateTestObjects(t)
    59  		httpmock.Activate()
    60  
    61  		// Expect the transaction api to be called and return an error
    62  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusInternalServerError, ""))
    63  
    64  		body, _ := json.Marshal(&models.InsolvencyRequest{})
    65  
    66  		res := serveHandleCreateProgressReport(body, mockService, helperService, true, rec)
    67  
    68  		So(res.Code, ShouldEqual, http.StatusInternalServerError)
    69  		So(res.Body.String(), ShouldContainSubstring, "error checking transaction status")
    70  	})
    71  
    72  	Convey("Transaction is already closed and cannot be updated", t, func() {
    73  		mockService, _, rec := mocks.CreateTestObjects(t)
    74  		httpmock.Activate()
    75  
    76  		// Expect the transaction api to be called and return an already closed transaction
    77  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponseClosed))
    78  
    79  		body, _ := json.Marshal(&models.InsolvencyRequest{})
    80  
    81  		res := serveHandleCreateProgressReport(body, mockService, helperService, true, rec)
    82  
    83  		So(res.Code, ShouldEqual, http.StatusForbidden)
    84  		So(res.Body.String(), ShouldContainSubstring, "already closed and cannot be updated")
    85  	})
    86  
    87  	Convey("Failed to read request body", t, func() {
    88  		mockService, _, rec := mocks.CreateTestObjects(t)
    89  		httpmock.Activate()
    90  
    91  		// Expect the transaction api to be called and return an open transaction
    92  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponse))
    93  
    94  		body := []byte(`{"first_name":error`)
    95  
    96  		res := serveHandleCreateProgressReport(body, mockService, helperService, true, rec)
    97  
    98  		So(res.Code, ShouldEqual, http.StatusBadRequest)
    99  		So(res.Body.String(), ShouldContainSubstring, fmt.Sprintf("failed to read request body for transaction %s", transactionID))
   100  	})
   101  
   102  	Convey("Incoming request has from date missing", t, func() {
   103  		mockService, _, rec := mocks.CreateTestObjects(t)
   104  		httpmock.Activate()
   105  
   106  		// Expect the transaction api to be called and return an open transaction
   107  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponse))
   108  
   109  		progressReport := generateProgressReport()
   110  		progressReport.FromDate = ""
   111  
   112  		body, _ := json.Marshal(progressReport)
   113  		res := serveHandleCreateProgressReport(body, mockService, helperService, true, rec)
   114  
   115  		So(res.Code, ShouldEqual, http.StatusBadRequest)
   116  		So(res.Body.String(), ShouldContainSubstring, "from_date is a required field")
   117  	})
   118  
   119  	Convey("Incoming request has to date missing", t, func() {
   120  		mockService, _, rec := mocks.CreateTestObjects(t)
   121  		httpmock.Activate()
   122  
   123  		// Expect the transaction api to be called and return an open transaction
   124  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponse))
   125  
   126  		progressReport := generateProgressReport()
   127  		progressReport.ToDate = ""
   128  
   129  		body, _ := json.Marshal(progressReport)
   130  
   131  		res := serveHandleCreateProgressReport(body, mockService, helperService, true, rec)
   132  
   133  		So(res.Code, ShouldEqual, http.StatusBadRequest)
   134  		So(res.Body.String(), ShouldContainSubstring, "to_date is a required field")
   135  	})
   136  
   137  	Convey("Incoming request has invalid from date format", t, func() {
   138  		mockService, _, rec := mocks.CreateTestObjects(t)
   139  		httpmock.Activate()
   140  
   141  		// Expect the transaction api to be called and return an open transaction
   142  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponse))
   143  
   144  		progressReport := generateProgressReport()
   145  		progressReport.FromDate = "21-01-01"
   146  
   147  		body, _ := json.Marshal(progressReport)
   148  
   149  		res := serveHandleCreateProgressReport(body, mockService, helperService, true, rec)
   150  
   151  		So(res.Code, ShouldEqual, http.StatusBadRequest)
   152  		So(res.Body.String(), ShouldContainSubstring, "from_date does not match the 2006-01-02 format")
   153  	})
   154  
   155  	Convey("Incoming request has invalid to date format", t, func() {
   156  		mockService, _, rec := mocks.CreateTestObjects(t)
   157  		httpmock.Activate()
   158  
   159  		// Expect the transaction api to be called and return an open transaction
   160  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponse))
   161  
   162  		progressReport := generateProgressReport()
   163  		progressReport.ToDate = "21-01-01"
   164  
   165  		body, _ := json.Marshal(progressReport)
   166  
   167  		res := serveHandleCreateProgressReport(body, mockService, helperService, true, rec)
   168  
   169  		So(res.Code, ShouldEqual, http.StatusBadRequest)
   170  		So(res.Body.String(), ShouldContainSubstring, "to_date does not match the 2006-01-02 format")
   171  	})
   172  
   173  	Convey("invalid from date - in the future", t, func() {
   174  		mockService, mockHelperService, rec := mocks.CreateTestObjects(t)
   175  
   176  		httpmock.Activate()
   177  
   178  		// Expect the transaction api to be called and return an open transaction
   179  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponse))
   180  
   181  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/company/1234", httpmock.NewStringResponder(http.StatusOK, companyProfileDateResponse("2000-06-26 00:00:00.000Z")))
   182  
   183  		progressReport := generateProgressReport()
   184  		progressReport.FromDate = time.Now().AddDate(0, 0, 1).Format("2006-01-02")
   185  
   186  		body, _ := json.Marshal(progressReport)
   187  		mockHelperService.EXPECT().HandleTransactionIdExistsValidation(gomock.Any(), gomock.Any(), transactionID).Return(true, transactionID).AnyTimes()
   188  		mockHelperService.EXPECT().HandleTransactionNotClosedValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   189  		mockHelperService.EXPECT().HandleBodyDecodedValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   190  		mockHelperService.EXPECT().GenerateEtag().Return("etag", nil).AnyTimes()
   191  		mockHelperService.EXPECT().HandleEtagGenerationValidation(gomock.Any()).Return(true).AnyTimes()
   192  		mockHelperService.EXPECT().HandleMandatoryFieldValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   193  		mockService.EXPECT().GetInsolvencyResource(transactionID).Return(generateInsolvencyResource(), nil)
   194  
   195  		res := serveHandleCreateProgressReport(body, mockService, mockHelperService, true, rec)
   196  
   197  		So(res.Code, ShouldEqual, http.StatusBadRequest)
   198  		So(res.Body.String(), ShouldContainSubstring, "from_date")
   199  		So(res.Body.String(), ShouldContainSubstring, "should not be in the future or before the company was incorporated")
   200  	})
   201  
   202  	Convey("invalid to date - in the future", t, func() {
   203  		mockService, mockHelperService, rec := mocks.CreateTestObjects(t)
   204  
   205  		httpmock.Activate()
   206  
   207  		// Expect the transaction api to be called and return an open transaction
   208  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponse))
   209  
   210  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/company/1234", httpmock.NewStringResponder(http.StatusOK, companyProfileDateResponse("2000-06-26 00:00:00.000Z")))
   211  
   212  		progressReport := generateProgressReport()
   213  		progressReport.ToDate = time.Now().AddDate(0, 0, 1).Format("2006-01-02")
   214  
   215  		body, _ := json.Marshal(progressReport)
   216  		mockHelperService.EXPECT().HandleTransactionIdExistsValidation(gomock.Any(), gomock.Any(), transactionID).Return(true, transactionID).AnyTimes()
   217  		mockHelperService.EXPECT().HandleTransactionNotClosedValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   218  		mockHelperService.EXPECT().HandleBodyDecodedValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   219  		mockHelperService.EXPECT().GenerateEtag().Return("etag", nil).AnyTimes()
   220  		mockHelperService.EXPECT().HandleEtagGenerationValidation(gomock.Any()).Return(true).AnyTimes()
   221  		mockHelperService.EXPECT().HandleMandatoryFieldValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   222  		mockService.EXPECT().GetInsolvencyResource(transactionID).Return(generateInsolvencyResource(), nil)
   223  
   224  		res := serveHandleCreateProgressReport(body, mockService, mockHelperService, true, rec)
   225  
   226  		So(res.Code, ShouldEqual, http.StatusBadRequest)
   227  		So(res.Body.String(), ShouldContainSubstring, "to_date")
   228  		So(res.Body.String(), ShouldContainSubstring, "should not be in the future or before the company was incorporated")
   229  	})
   230  
   231  	Convey("invalid from date - before incorporation date", t, func() {
   232  		mockService, mockHelperService, rec := mocks.CreateTestObjects(t)
   233  
   234  		httpmock.Activate()
   235  
   236  		// Expect the transaction api to be called and return an open transaction
   237  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponse))
   238  
   239  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/company/1234", httpmock.NewStringResponder(http.StatusOK, companyProfileDateResponse("2000-06-26 00:00:00.000Z")))
   240  
   241  		progressReport := generateProgressReport()
   242  		progressReport.FromDate = "1999-01-02"
   243  
   244  		body, _ := json.Marshal(progressReport)
   245  		mockHelperService.EXPECT().HandleTransactionIdExistsValidation(gomock.Any(), gomock.Any(), transactionID).Return(true, transactionID).AnyTimes()
   246  		mockHelperService.EXPECT().HandleTransactionNotClosedValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   247  		mockHelperService.EXPECT().HandleBodyDecodedValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   248  		mockHelperService.EXPECT().GenerateEtag().Return("etag", nil).AnyTimes()
   249  		mockHelperService.EXPECT().HandleEtagGenerationValidation(gomock.Any()).Return(true).AnyTimes()
   250  		mockHelperService.EXPECT().HandleMandatoryFieldValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   251  		mockService.EXPECT().GetInsolvencyResource(transactionID).Return(generateInsolvencyResource(), nil)
   252  
   253  		res := serveHandleCreateProgressReport(body, mockService, mockHelperService, true, rec)
   254  
   255  		So(res.Code, ShouldEqual, http.StatusBadRequest)
   256  		So(res.Body.String(), ShouldContainSubstring, "from_date")
   257  		So(res.Body.String(), ShouldContainSubstring, "should not be in the future or before the company was incorporated")
   258  	})
   259  
   260  	Convey("invalid to date - before incorporation date", t, func() {
   261  		mockService, mockHelperService, rec := mocks.CreateTestObjects(t)
   262  
   263  		httpmock.Activate()
   264  
   265  		// Expect the transaction api to be called and return an open transaction
   266  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponse))
   267  
   268  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/company/1234", httpmock.NewStringResponder(http.StatusOK, companyProfileDateResponse("2000-06-26 00:00:00.000Z")))
   269  
   270  		progressReport := generateProgressReport()
   271  		progressReport.ToDate = "1999-06-26"
   272  
   273  		body, _ := json.Marshal(progressReport)
   274  		mockHelperService.EXPECT().HandleTransactionIdExistsValidation(gomock.Any(), gomock.Any(), transactionID).Return(true, transactionID).AnyTimes()
   275  		mockHelperService.EXPECT().HandleTransactionNotClosedValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   276  		mockHelperService.EXPECT().HandleBodyDecodedValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   277  		mockHelperService.EXPECT().GenerateEtag().Return("etag", nil).AnyTimes()
   278  		mockHelperService.EXPECT().HandleEtagGenerationValidation(gomock.Any()).Return(true).AnyTimes()
   279  		mockHelperService.EXPECT().HandleMandatoryFieldValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   280  		mockService.EXPECT().GetInsolvencyResource(transactionID).Return(generateInsolvencyResource(), nil)
   281  
   282  		res := serveHandleCreateProgressReport(body, mockService, mockHelperService, true, rec)
   283  
   284  		So(res.Code, ShouldEqual, http.StatusBadRequest)
   285  		So(res.Body.String(), ShouldContainSubstring, "to_date")
   286  		So(res.Body.String(), ShouldContainSubstring, "should not be in the future or before the company was incorporated")
   287  	})
   288  
   289  	Convey("invalid to date - to date is before from date", t, func() {
   290  		mockService, mockHelperService, rec := mocks.CreateTestObjects(t)
   291  
   292  		httpmock.Activate()
   293  
   294  		// Expect the transaction api to be called and return an open transaction
   295  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponse))
   296  
   297  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/company/1234", httpmock.NewStringResponder(http.StatusOK, companyProfileDateResponse("2000-06-26 00:00:00.000Z")))
   298  
   299  		progressReport := generateProgressReport()
   300  		progressReport.FromDate = "2021-06-27"
   301  		progressReport.ToDate = "2021-06-26"
   302  
   303  		body, _ := json.Marshal(progressReport)
   304  		mockHelperService.EXPECT().HandleTransactionIdExistsValidation(gomock.Any(), gomock.Any(), transactionID).Return(true, transactionID).AnyTimes()
   305  		mockHelperService.EXPECT().HandleTransactionNotClosedValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   306  		mockHelperService.EXPECT().HandleBodyDecodedValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   307  		mockHelperService.EXPECT().GenerateEtag().Return("etag", nil).AnyTimes()
   308  		mockHelperService.EXPECT().HandleEtagGenerationValidation(gomock.Any()).Return(true).AnyTimes()
   309  		mockHelperService.EXPECT().HandleMandatoryFieldValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   310  		mockService.EXPECT().GetInsolvencyResource(transactionID).Return(generateInsolvencyResource(), nil)
   311  
   312  		res := serveHandleCreateProgressReport(body, mockService, mockHelperService, true, rec)
   313  
   314  		So(res.Code, ShouldEqual, http.StatusBadRequest)
   315  		So(res.Body.String(), ShouldContainSubstring, "to_date")
   316  		So(res.Body.String(), ShouldContainSubstring, "should not be before from_date")
   317  	})
   318  
   319  	Convey("Incoming request has attachments missing", t, func() {
   320  		mockService, _, rec := mocks.CreateTestObjects(t)
   321  		httpmock.Activate()
   322  
   323  		// Expect the transaction api to be called and return an open transaction
   324  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponse))
   325  
   326  		statement := generateProgressReport()
   327  		statement.Attachments = nil
   328  		body, _ := json.Marshal(statement)
   329  
   330  		res := serveHandleCreateProgressReport(body, mockService, helperService, true, rec)
   331  
   332  		So(res.Code, ShouldEqual, http.StatusBadRequest)
   333  		So(res.Body.String(), ShouldContainSubstring, "attachments is a required field")
   334  	})
   335  
   336  	Convey("Attachment is not associated with transaction", t, func() {
   337  		mockService, _, rec := mocks.CreateTestObjects(t)
   338  		httpmock.Activate()
   339  
   340  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/company/1234", httpmock.NewStringResponder(http.StatusOK, companyProfileDateResponse("2000-06-26 00:00:00.000Z")))
   341  
   342  		// Expect the transaction api to be called and return an open transaction
   343  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponse))
   344  
   345  		progressReport := generateProgressReport()
   346  		body, _ := json.Marshal(progressReport)
   347  		mockService.EXPECT().GetInsolvencyResource(transactionID).Return(generateInsolvencyResource(), nil)
   348  		// Expect GetAttachmentFromInsolvencyResource to be called once and return an empty attachment model, nil
   349  		mockService.EXPECT().GetAttachmentFromInsolvencyResource(transactionID, progressReport.Attachments[0]).Return(models.AttachmentResourceDao{}, nil)
   350  
   351  		res := serveHandleCreateProgressReport(body, mockService, helperService, true, rec)
   352  
   353  		So(res.Code, ShouldEqual, http.StatusInternalServerError)
   354  		So(res.Body.String(), ShouldContainSubstring, "attachment not found on transaction")
   355  	})
   356  
   357  	Convey("Failed to validate progress report", t, func() {
   358  		mockService, mockHelperService, rec := mocks.CreateTestObjects(t)
   359  		httpmock.Activate()
   360  
   361  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/company/1234", httpmock.NewStringResponder(http.StatusOK, companyProfileDateResponse("2000-06-26 00:00:00.000Z")))
   362  
   363  		// Expect the transaction api to be called and return an open transaction
   364  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponse))
   365  
   366  		progressReport := generateProgressReport()
   367  
   368  		body, _ := json.Marshal(progressReport)
   369  		mockHelperService.EXPECT().HandleTransactionIdExistsValidation(gomock.Any(), gomock.Any(), transactionID).Return(true, transactionID).AnyTimes()
   370  		mockHelperService.EXPECT().HandleTransactionNotClosedValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   371  		mockHelperService.EXPECT().HandleBodyDecodedValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   372  		mockHelperService.EXPECT().GenerateEtag().Return("etag", nil).AnyTimes()
   373  		mockHelperService.EXPECT().HandleEtagGenerationValidation(gomock.Any()).Return(true).AnyTimes()
   374  		mockHelperService.EXPECT().HandleMandatoryFieldValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   375  		mockService.EXPECT().GetInsolvencyResource(transactionID).Return(models.InsolvencyResourceDao{}, fmt.Errorf("error"))
   376  
   377  		res := serveHandleCreateProgressReport(body, mockService, mockHelperService, true, rec)
   378  
   379  		So(res.Code, ShouldEqual, http.StatusInternalServerError)
   380  		So(res.Body.String(), ShouldContainSubstring, "there was a problem handling your request for transaction ID")
   381  	})
   382  
   383  	Convey("Validation errors are present - multiple attachments", t, func() {
   384  		mockService, mockHelperService, rec := mocks.CreateTestObjects(t)
   385  		httpmock.Activate()
   386  
   387  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/company/1234", httpmock.NewStringResponder(http.StatusOK, companyProfileDateResponse("2000-06-26 00:00:00.000Z")))
   388  
   389  		// Expect the transaction api to be called and return an open transaction
   390  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponse))
   391  
   392  		progressReport := generateProgressReport()
   393  		progressReport.Attachments = []string{
   394  			"1234567890",
   395  			"0987654321",
   396  		}
   397  
   398  		body, _ := json.Marshal(progressReport)
   399  		mockHelperService.EXPECT().HandleTransactionIdExistsValidation(gomock.Any(), gomock.Any(), transactionID).Return(true, transactionID).AnyTimes()
   400  		mockHelperService.EXPECT().HandleTransactionNotClosedValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   401  		mockHelperService.EXPECT().HandleBodyDecodedValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   402  		mockHelperService.EXPECT().GenerateEtag().Return("etag", nil).AnyTimes()
   403  		mockHelperService.EXPECT().HandleEtagGenerationValidation(gomock.Any()).Return(true).AnyTimes()
   404  		mockHelperService.EXPECT().HandleMandatoryFieldValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   405  		mockService.EXPECT().GetInsolvencyResource(transactionID).Return(generateInsolvencyResource(), nil)
   406  
   407  		res := serveHandleCreateProgressReport(body, mockService, mockHelperService, true, rec)
   408  
   409  		So(res.Code, ShouldEqual, http.StatusBadRequest)
   410  		So(res.Body.String(), ShouldContainSubstring, "please supply only one attachment")
   411  	})
   412  
   413  	Convey("Validation errors are present - no attachment is present", t, func() {
   414  		mockService, mockHelperService, rec := mocks.CreateTestObjects(t)
   415  		httpmock.Activate()
   416  
   417  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/company/1234", httpmock.NewStringResponder(http.StatusOK, companyProfileDateResponse("2000-06-26 00:00:00.000Z")))
   418  
   419  		// Expect the transaction api to be called and return an open transaction
   420  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponse))
   421  
   422  		progressReport := generateProgressReport()
   423  		progressReport.Attachments = []string{}
   424  
   425  		body, _ := json.Marshal(progressReport)
   426  		mockHelperService.EXPECT().HandleTransactionIdExistsValidation(gomock.Any(), gomock.Any(), transactionID).Return(true, transactionID).AnyTimes()
   427  		mockHelperService.EXPECT().HandleTransactionNotClosedValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   428  		mockHelperService.EXPECT().HandleBodyDecodedValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   429  		mockHelperService.EXPECT().GenerateEtag().Return("etag", nil).AnyTimes()
   430  		mockHelperService.EXPECT().HandleEtagGenerationValidation(gomock.Any()).Return(true).AnyTimes()
   431  		mockHelperService.EXPECT().HandleMandatoryFieldValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   432  		mockService.EXPECT().GetInsolvencyResource(transactionID).Return(generateInsolvencyResource(), nil)
   433  
   434  		res := serveHandleCreateProgressReport(body, mockService, mockHelperService, true, rec)
   435  
   436  		So(res.Code, ShouldEqual, http.StatusBadRequest)
   437  		So(res.Body.String(), ShouldContainSubstring, "please supply only one attachment")
   438  	})
   439  
   440  	Convey("Attachment is not of type progress-report", t, func() {
   441  		mockService, _, rec := mocks.CreateTestObjects(t)
   442  		httpmock.Activate()
   443  
   444  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/company/1234", httpmock.NewStringResponder(http.StatusOK, companyProfileDateResponse("2000-06-26 00:00:00.000Z")))
   445  
   446  		// Expect the transaction api to be called and return an open transaction
   447  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponse))
   448  
   449  		progressReport := generateProgressReport()
   450  
   451  		attachment := generateAttachment()
   452  		attachment.Type = "not-progress-report"
   453  
   454  		body, _ := json.Marshal(progressReport)
   455  		mockService.EXPECT().GetInsolvencyResource(transactionID).Return(generateInsolvencyResource(), nil)
   456  		// Expect GetAttachmentFromInsolvencyResource to be called once and return attachment, nil
   457  		mockService.EXPECT().GetAttachmentFromInsolvencyResource(transactionID, progressReport.Attachments[0]).Return(attachment, nil)
   458  
   459  		res := serveHandleCreateProgressReport(body, mockService, helperService, true, rec)
   460  
   461  		So(res.Code, ShouldEqual, http.StatusBadRequest)
   462  		So(res.Body.String(), ShouldContainSubstring, "attachment is not a progress-report")
   463  	})
   464  
   465  	Convey("Generic error when adding progress report resource to mongo", t, func() {
   466  		mockService, _, rec := mocks.CreateTestObjects(t)
   467  		httpmock.Activate()
   468  
   469  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/company/1234", httpmock.NewStringResponder(http.StatusOK, companyProfileDateResponse("2000-06-26 00:00:00.000Z")))
   470  
   471  		// Expect the transaction api to be called and return an open transaction
   472  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponse))
   473  
   474  		progressReport := generateProgressReport()
   475  
   476  		attachment := generateAttachment()
   477  		attachment.Type = "progress-report"
   478  
   479  		body, _ := json.Marshal(progressReport)
   480  		// Expect GetAttachmentFromInsolvencyResource to be called once and return attachment, nil
   481  		mockService.EXPECT().GetAttachmentFromInsolvencyResource(transactionID, progressReport.Attachments[0]).Return(attachment, nil)
   482  		// Expect CreateProgressReportResource to be called and return an error
   483  		mockService.EXPECT().CreateProgressReportResource(gomock.Any(), transactionID).Return(http.StatusInternalServerError, fmt.Errorf("there was a problem handling your request for transaction %s", transactionID))
   484  		mockService.EXPECT().GetInsolvencyResource(transactionID).Return(generateInsolvencyResource(), nil)
   485  
   486  		res := serveHandleCreateProgressReport(body, mockService, helperService, true, rec)
   487  
   488  		So(res.Code, ShouldEqual, http.StatusInternalServerError)
   489  		So(res.Body.String(), ShouldContainSubstring, "there was a problem handling your request")
   490  	})
   491  
   492  	Convey("Error adding progress report resource to mongo - insolvency case not found", t, func() {
   493  		mockService, _, rec := mocks.CreateTestObjects(t)
   494  		httpmock.Activate()
   495  
   496  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/company/1234", httpmock.NewStringResponder(http.StatusOK, companyProfileDateResponse("2000-06-26 00:00:00.000Z")))
   497  
   498  		// Expect the transaction api to be called and return an open transaction
   499  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponse))
   500  
   501  		progressReport := generateProgressReport()
   502  
   503  		attachment := generateAttachment()
   504  		attachment.Type = "progress-report"
   505  
   506  		body, _ := json.Marshal(progressReport)
   507  		mockService.EXPECT().GetInsolvencyResource(transactionID).Return(generateInsolvencyResource(), nil)
   508  		// Expect GetAttachmentFromInsolvencyResource to be called once and return attachment, nil
   509  		mockService.EXPECT().GetAttachmentFromInsolvencyResource(transactionID, progressReport.Attachments[0]).Return(attachment, nil)
   510  		// Expect CreateProgressReportResource to be called and return an error
   511  		mockService.EXPECT().CreateProgressReportResource(gomock.Any(), transactionID).Return(http.StatusNotFound, fmt.Errorf("there was a problem handling your request for transaction %s not found", transactionID))
   512  
   513  		res := serveHandleCreateProgressReport(body, mockService, helperService, true, rec)
   514  
   515  		So(res.Code, ShouldEqual, http.StatusNotFound)
   516  		So(res.Body.String(), ShouldContainSubstring, "not found")
   517  	})
   518  
   519  	Convey("Successfully add insolvency resource to mongo", t, func() {
   520  		mockService, mockHelperService, rec := mocks.CreateTestObjects(t)
   521  		httpmock.Activate()
   522  
   523  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/company/1234", httpmock.NewStringResponder(http.StatusOK, companyProfileDateResponse("2000-06-26 00:00:00.000Z")))
   524  
   525  		// Expect the transaction api to be called and return an open transaction
   526  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponse))
   527  
   528  		progressReport := generateProgressReport()
   529  
   530  		attachment := generateAttachment()
   531  		attachment.Type = "progress-report"
   532  
   533  		body, _ := json.Marshal(progressReport)
   534  
   535  		mockHelperService.EXPECT().HandleTransactionIdExistsValidation(gomock.Any(), gomock.Any(), transactionID).Return(true, transactionID).AnyTimes()
   536  		mockHelperService.EXPECT().HandleTransactionNotClosedValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   537  		mockHelperService.EXPECT().HandleBodyDecodedValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   538  		mockHelperService.EXPECT().GenerateEtag().Return("etag", nil).AnyTimes()
   539  		mockHelperService.EXPECT().HandleEtagGenerationValidation(gomock.Any()).Return(true).AnyTimes()
   540  		mockHelperService.EXPECT().HandleMandatoryFieldValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   541  		mockService.EXPECT().GetInsolvencyResource(transactionID).Return(generateInsolvencyResource(), nil)
   542  		// Expect GetAttachmentFromInsolvencyResource to be called once and return attachment, nil
   543  		mockService.EXPECT().GetAttachmentFromInsolvencyResource(transactionID, progressReport.Attachments[0]).Return(attachment, nil)
   544  		mockHelperService.EXPECT().HandleAttachmentValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   545  		mockService.EXPECT().CreateProgressReportResource(gomock.Any(), transactionID).Return(http.StatusOK, nil)
   546  		mockHelperService.EXPECT().HandleCreateResourceValidation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes()
   547  
   548  		res := serveHandleCreateProgressReport(body, mockService, mockHelperService, true, rec)
   549  
   550  		So(res.Code, ShouldEqual, http.StatusCreated)
   551  		So(res.Body.String(), ShouldContainSubstring, "\"kind\":\"insolvency-resource#progress-report\"")
   552  	})
   553  }
   554  
   555  func serveHandleGetProgressReport(service dao.Service, tranIDSet bool) *httptest.ResponseRecorder {
   556  	path := "/transactions/123456789/insolvency/progress-report"
   557  	req := httptest.NewRequest(http.MethodPost, path, nil)
   558  	if tranIDSet {
   559  		req = mux.SetURLVars(req, map[string]string{"transaction_id": transactionID})
   560  	}
   561  	rec := httptest.NewRecorder()
   562  
   563  	handler := HandleGetProgressReport(service)
   564  	handler.ServeHTTP(rec, req)
   565  
   566  	return rec
   567  }
   568  
   569  func TestUnitHandleGetProgressReport(t *testing.T) {
   570  	err := os.Chdir("..")
   571  	if err != nil {
   572  		log.ErrorR(nil, fmt.Errorf("error accessing root directory"))
   573  	}
   574  
   575  	Convey("Must need a transaction ID in the url", t, func() {
   576  		mockCtrl := gomock.NewController(t)
   577  		defer mockCtrl.Finish()
   578  
   579  		res := serveHandleGetProgressReport(mock_dao.NewMockService(mockCtrl), false)
   580  
   581  		So(res.Code, ShouldEqual, http.StatusBadRequest)
   582  	})
   583  
   584  	Convey("Failed to get progress report from Insolvency resource", t, func() {
   585  		httpmock.Activate()
   586  		mockCtrl := gomock.NewController(t)
   587  		defer httpmock.DeactivateAndReset()
   588  		defer mockCtrl.Finish()
   589  		mockService := mock_dao.NewMockService(mockCtrl)
   590  
   591  		// Expect GetProgressReportResource to be called once and return an error
   592  		mockService.EXPECT().GetProgressReportResource(transactionID).Return(&models.ProgressReportResourceDao{}, fmt.Errorf("failed to get progress report from insolvency resource in db for transaction [%s]: %v", transactionID, err))
   593  
   594  		res := serveHandleGetProgressReport(mockService, true)
   595  
   596  		So(res.Code, ShouldEqual, http.StatusInternalServerError)
   597  	})
   598  
   599  	Convey("Progress report was not found on supplied transaction", t, func() {
   600  		httpmock.Activate()
   601  		mockCtrl := gomock.NewController(t)
   602  		defer httpmock.DeactivateAndReset()
   603  		defer mockCtrl.Finish()
   604  		mockService := mock_dao.NewMockService(mockCtrl)
   605  
   606  		// Expect GetProgressReportResource to be called once and return nil
   607  		mockService.EXPECT().GetProgressReportResource(transactionID).Return(&models.ProgressReportResourceDao{}, nil)
   608  
   609  		res := serveHandleGetProgressReport(mockService, true)
   610  
   611  		So(res.Code, ShouldEqual, http.StatusNotFound)
   612  	})
   613  
   614  	Convey("Success - Progress report was retrieved from insolvency resource", t, func() {
   615  		httpmock.Activate()
   616  		mockCtrl := gomock.NewController(t)
   617  		defer httpmock.DeactivateAndReset()
   618  		defer mockCtrl.Finish()
   619  		mockService := mock_dao.NewMockService(mockCtrl)
   620  
   621  		progressReport := models.ProgressReportResourceDao{
   622  			Etag:          "6f143c1f8109d834263eb764c5f020a0ae3ff78ee1789477179cb80f",
   623  			Kind:          "insolvency-resource#progress-report",
   624  			FromDate: "2021-06-06",
   625  			ToDate:   "2022-06-05",
   626  			Attachments: []string{
   627  				"1223-3445-5667",
   628  			},
   629  			Links: models.ProgressReportResourceLinksDao{
   630  				Self: "/transactions/12345678/insolvency/progress-report",
   631  			},
   632  		}
   633  
   634  		// Expect GetProgressReportResource to be called once and return statement of affairs
   635  		mockService.EXPECT().GetProgressReportResource(transactionID).Return(&progressReport, nil)
   636  
   637  		res := serveHandleGetProgressReport(mockService, true)
   638  
   639  		So(res.Code, ShouldEqual, http.StatusOK)
   640  		So(res.Body.String(), ShouldContainSubstring, "etag")
   641  		So(res.Body.String(), ShouldContainSubstring, "kind")
   642  		So(res.Body.String(), ShouldContainSubstring, "links")
   643  		So(res.Body.String(), ShouldContainSubstring, "from_date")
   644  		So(res.Body.String(), ShouldContainSubstring, "to_date")
   645  		So(res.Body.String(), ShouldContainSubstring, "attachments")
   646  	})
   647  }
   648  
   649  func serveHandleDeleteProgressReport(service dao.Service, helperService utils.HelperService,tranIDSet bool) *httptest.ResponseRecorder {
   650  	path := "/transactions/123456789/insolvency/progress-report"
   651  	req := httptest.NewRequest(http.MethodDelete, path, nil)
   652  	if tranIDSet {
   653  		req = mux.SetURLVars(req, map[string]string{"transaction_id": transactionID})
   654  	}
   655  	res := httptest.NewRecorder()
   656  
   657  	handler := HandleDeleteProgressReport(service, helperService)
   658  	handler.ServeHTTP(res, req)
   659  
   660  	return res
   661  }
   662  
   663  func TestUnitHandleDeleteProgressReport(t *testing.T) {
   664  	err := os.Chdir("..")
   665  	if err != nil {
   666  		log.ErrorR(nil, fmt.Errorf("error accessing root directory"))
   667  	}
   668  
   669  	helperService := utils.NewHelperService()
   670  
   671  	Convey("Must need a transaction ID in the url", t, func() {
   672  		mockCtrl := gomock.NewController(t)
   673  		defer mockCtrl.Finish()
   674  
   675  		res := serveHandleDeleteProgressReport(mock_dao.NewMockService(mockCtrl), helperService, false)
   676  
   677  		So(res.Code, ShouldEqual, http.StatusBadRequest)
   678  	})
   679  
   680  	Convey("Error checking if transaction is closed against transaction api", t, func() {
   681  		httpmock.Activate()
   682  		mockCtrl := gomock.NewController(t)
   683  		defer httpmock.DeactivateAndReset()
   684  		defer mockCtrl.Finish()
   685  
   686  		// Expect the transaction api to be called and return an error
   687  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusInternalServerError, ""))
   688  
   689  		res := serveHandleDeleteProgressReport(mock_dao.NewMockService(mockCtrl), helperService,true)
   690  
   691  		So(res.Code, ShouldEqual, http.StatusInternalServerError)
   692  	})
   693  
   694  	Convey("Transaction is already closed and cannot be updated", t, func() {
   695  		httpmock.Activate()
   696  		mockCtrl := gomock.NewController(t)
   697  		defer httpmock.DeactivateAndReset()
   698  		defer mockCtrl.Finish()
   699  
   700  		// Expect the transaction api to be called and return an already closed transaction
   701  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponseClosed))
   702  
   703  		res := serveHandleDeleteProgressReport(mock_dao.NewMockService(mockCtrl), helperService, true)
   704  
   705  		So(res.Code, ShouldEqual, http.StatusForbidden)
   706  	})
   707  
   708  	Convey("Error when deleting progress report from DB", t, func() {
   709  		httpmock.Activate()
   710  		mockCtrl := gomock.NewController(t)
   711  		defer mockCtrl.Finish()
   712  		defer httpmock.DeactivateAndReset()
   713  
   714  		// Expect the transaction api to be called and return an open transaction
   715  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponse))
   716  
   717  		// Expect the deletion of progress report to return an error
   718  		mockService := mock_dao.NewMockService(mockCtrl)
   719  		mockService.EXPECT().DeleteProgressReportResource(transactionID).Return(http.StatusInternalServerError, fmt.Errorf("err"))
   720  
   721  		res := serveHandleDeleteProgressReport(mockService, helperService, true)
   722  
   723  		So(res.Code, ShouldEqual, http.StatusInternalServerError)
   724  	})
   725  
   726  	Convey("Progress report not found when deleting from DB", t, func() {
   727  		httpmock.Activate()
   728  		mockCtrl := gomock.NewController(t)
   729  		defer mockCtrl.Finish()
   730  		defer httpmock.DeactivateAndReset()
   731  
   732  		// Expect the transaction api to be called and return an open transaction
   733  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponse))
   734  
   735  		mockService := mock_dao.NewMockService(mockCtrl)
   736  		mockService.EXPECT().DeleteProgressReportResource(transactionID).Return(http.StatusNotFound, fmt.Errorf("err"))
   737  
   738  		res := serveHandleDeleteProgressReport(mockService, helperService, true)
   739  
   740  		So(res.Code, ShouldEqual, http.StatusNotFound)
   741  	})
   742  
   743  	Convey("Successfully delete progress report from DB", t, func() {
   744  		httpmock.Activate()
   745  		mockCtrl := gomock.NewController(t)
   746  		defer mockCtrl.Finish()
   747  		defer httpmock.DeactivateAndReset()
   748  
   749  		// Expect the transaction api to be called and return an open transaction
   750  		httpmock.RegisterResponder(http.MethodGet, "https://api.companieshouse.gov.uk/transactions/12345678", httpmock.NewStringResponder(http.StatusOK, transactionProfileResponse))
   751  
   752  		mockService := mock_dao.NewMockService(mockCtrl)
   753  		mockService.EXPECT().DeleteProgressReportResource(transactionID).Return(http.StatusNoContent, nil)
   754  
   755  		res := serveHandleDeleteProgressReport(mockService, helperService, true)
   756  
   757  		So(res.Code, ShouldEqual, http.StatusNoContent)
   758  	})
   759  
   760  }
   761  
   762  func generateProgressReport() models.ProgressReport {
   763  	return models.ProgressReport{
   764  		FromDate: "2021-06-06",
   765  		ToDate:   "2021-06-07",
   766  		Attachments: []string{
   767  			"123456789",
   768  		},
   769  	}
   770  }