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 }