public async Task Should_change_hearing_status_to_cancelled() { var request = new UpdateBookingStatusRequest { UpdatedBy = "*****@*****.**", Status = UpdateBookingStatus.Cancelled, CancelReason = "Adjournment" }; var hearingId = Guid.NewGuid(); var hearing = GetHearing("123"); QueryHandlerMock .Setup(x => x.Handle <GetHearingByIdQuery, VideoHearing>(It.IsAny <GetHearingByIdQuery>())) .ReturnsAsync(hearing); var result = await Controller.UpdateBookingStatus(hearingId, request); result.Should().NotBeNull(); var objectResult = (NoContentResult)result; objectResult.StatusCode.Should().Be((int)HttpStatusCode.NoContent); var message = SbQueueClient.ReadMessageFromQueue(); var typedMessage = (HearingCancelledIntegrationEvent)message.IntegrationEvent; typedMessage.Should().NotBeNull(); typedMessage.HearingId.Should().Be(hearingId); }
public void Setup() { _bookingsApiClient = new Mock <IBookingsApiClient>(); _userIdentity = new Mock <IUserIdentity>(); _userAccountService = new Mock <IUserAccountService>(); _editHearingRequestValidator = new Mock <IValidator <EditHearingRequest> >(); _videoApiMock = new Mock <IVideoApiClient>(); _pollyRetryServiceMock = new Mock <IPollyRetryService>(); _notificationApiMock = new Mock <INotificationApiClient>(); _participantGroupLogger = new Mock <ILogger <HearingsService> >(); _hearingsService = new HearingsService(_pollyRetryServiceMock.Object, _userAccountService.Object, _notificationApiMock.Object, _videoApiMock.Object, _bookingsApiClient.Object, _participantGroupLogger.Object); _controller = new AdminWebsite.Controllers.HearingsController(_bookingsApiClient.Object, _userIdentity.Object, _userAccountService.Object, _editHearingRequestValidator.Object, new Mock <ILogger <AdminWebsite.Controllers.HearingsController> >().Object, _hearingsService, Mock.Of <IPublicHolidayRetriever>()); _guid = Guid.NewGuid(); _updateBookingStatusRequest = new UpdateBookingStatusRequest() { Status = UpdateBookingStatus.Cancelled, UpdatedBy = "admin user" }; }
public async Task Should_change_hearing_status_to_created_and_send_event_notification() { var request = new UpdateBookingStatusRequest { UpdatedBy = "*****@*****.**", Status = UpdateBookingStatus.Created }; var hearingId = Guid.NewGuid(); var hearing = GetHearing("123"); QueryHandlerMock .Setup(x => x.Handle <GetHearingByIdQuery, VideoHearing>(It.IsAny <GetHearingByIdQuery>())) .ReturnsAsync(hearing); var result = await Controller.UpdateBookingStatus(hearingId, request); result.Should().NotBeNull(); var objectResult = (NoContentResult)result; objectResult.StatusCode.Should().Be((int)HttpStatusCode.NoContent); var message = SbQueueClient.ReadMessageFromQueue(); var typedMessage = (HearingIsReadyForVideoIntegrationEvent)message.IntegrationEvent; typedMessage.Should().NotBeNull(); typedMessage.Hearing.HearingId.Should().Be(hearing.Id); typedMessage.Hearing.GroupId.Should().Be(hearing.SourceId.GetValueOrDefault()); }
public UpdateBookingRequestBuilder() { _request = new UpdateBookingStatusRequest { Status = UpdateBookingStatus.Created, UpdatedBy = UserData.DEFAULT_UPDATED_BY_USER }; }
public ConfirmHearingBuilder() { _request = new UpdateBookingStatusRequest() { CancelReason = null, Status = UpdateBookingStatus.Created, UpdatedBy = HearingsData.UPDATED_BY }; }
public async Task <IActionResult> UpdateBookingStatus(Guid hearingId, UpdateBookingStatusRequest updateBookingStatusRequest) { if (hearingId == Guid.Empty) { ModelState.AddModelError(nameof(hearingId), $"Please provide a valid {nameof(hearingId)}"); return(BadRequest(ModelState)); } var result = new UpdateBookingStatusRequestValidation().Validate(updateBookingStatusRequest); if (!result.IsValid) { ModelState.AddFluentValidationErrors(result.Errors); return(BadRequest(ModelState)); } try { var bookingStatus = MapUpdateBookingStatus(updateBookingStatusRequest.Status); var command = new UpdateHearingStatusCommand(hearingId, bookingStatus, updateBookingStatusRequest.UpdatedBy, updateBookingStatusRequest.CancelReason); await _commandHandler.Handle(command); switch (bookingStatus) { case BookingStatus.Booked: break; case BookingStatus.Created: var queriedVideoHearing = await GetHearingToPublish(hearingId); var createVideoHearingEvent = new HearingIsReadyForVideoIntegrationEvent(queriedVideoHearing); await _eventPublisher.PublishAsync(createVideoHearingEvent); break; case BookingStatus.Cancelled: await _eventPublisher.PublishAsync(new HearingCancelledIntegrationEvent(hearingId)); break; default: break; } return(NoContent()); } catch (HearingNotFoundException) { return(NotFound()); } catch (DomainRuleException exception) { exception.ValidationFailures.ForEach(x => ModelState.AddModelError(x.Name, x.Message)); return(Conflict(ModelState)); } }
public async Task Should_pass_validation_when_status_is_cancelled_and_cancel_reason_is_empty() { request = new UpdateBookingStatusRequest(); request.Status = UpdateBookingStatus.Cancelled; request.UpdatedBy = "TestUser"; var result = await _validator.ValidateAsync(request); result.IsValid.Should().BeFalse(); result.Errors[0].ErrorMessage.Should().Be("Cancel reason is required when a hearing is cancelled"); }
public async Task UpdateBookingStatusPolling(Guid hearingId, UpdateBookingStatusRequest request) { try { await _retryPolicy.ExecuteAsync(() => _bookingsApiClient.UpdateBookingStatusAsync(hearingId, request)); } catch (Exception e) { _logger.LogError(e, "Encountered error '{message}' after {timeout} seconds.", e.Message, RETRIES ^ 2); throw; } }
public async Task UpdateBookingStatus_returns_false_response_when_video_api_throws() { _userIdentity.Setup(x => x.GetUserIdentityName()).Returns("test"); var updateCreatedStatus = new UpdateBookingStatusRequest { UpdatedBy = "test", CancelReason = "", Status = UpdateBookingStatus.Created }; var hearingId = Guid.NewGuid(); var expectedConferenceDetailsResponse = new ConferenceDetailsResponse { Id = Guid.NewGuid(), HearingId = hearingId, MeetingRoom = new MeetingRoomResponse { AdminUri = "admin", JudgeUri = "judge", ParticipantUri = "participant", PexipNode = "pexip" } }; _bookingsApiClient.Setup(x => x.UpdateBookingStatusAsync(hearingId, updateCreatedStatus)); _bookingsApiClient.Setup(x => x.UpdateBookingStatusAsync(hearingId, It.IsAny <UpdateBookingStatusRequest>())); _pollyRetryServiceMock.Setup(x => x.WaitAndRetryAsync <VideoApiException, ConferenceDetailsResponse> ( It.IsAny <int>(), It.IsAny <Func <int, TimeSpan> >(), It.IsAny <Action <int> >(), It.IsAny <Func <ConferenceDetailsResponse, bool> >(), It.IsAny <Func <Task <ConferenceDetailsResponse> > >() )) .Callback(async(int retries, Func <int, TimeSpan> sleepDuration, Action <int> retryAction, Func <ConferenceDetailsResponse, bool> handleResultCondition, Func <Task <ConferenceDetailsResponse> > executeFunction) => { sleepDuration(1); retryAction(1); handleResultCondition(expectedConferenceDetailsResponse); await executeFunction(); }) .ThrowsAsync(new VideoApiException("", 0, "", null, null)); var response = await _controller.UpdateBookingStatus(hearingId, updateCreatedStatus); var result = (OkObjectResult)response; result.StatusCode.Should().Be(StatusCodes.Status200OK); result.Value.Should().NotBeNull().And.BeAssignableTo <UpdateBookingStatusResponse>().Subject.Success.Should().BeFalse(); _bookingsApiClient.Verify(x => x.UpdateBookingStatusAsync(hearingId, updateCreatedStatus), Times.Once); _bookingsApiClient.Verify(x => x.UpdateBookingStatusAsync(hearingId, It.Is <UpdateBookingStatusRequest>(pred => pred.Status == UpdateBookingStatus.Failed)), Times.Once); }
public async Task Should_not_update_booking_and_return_badrequest_with_an_invalid_hearingid() { var request = new UpdateBookingStatusRequest(); var hearingId = Guid.Empty; var result = await Controller.UpdateBookingStatus(hearingId, request); result.Should().NotBeNull(); var objectResult = (BadRequestObjectResult)result; objectResult.StatusCode.Should().Be((int)HttpStatusCode.BadRequest); ((SerializableError)objectResult.Value).ContainsKeyAndErrorMessage(nameof(hearingId), $"Please provide a valid {nameof(hearingId)}"); }
public void UpdateBookingStatus_throws_when_bookings_api_exception() { _userIdentity.Setup(x => x.GetUserIdentityName()).Returns("test"); var request = new UpdateBookingStatusRequest { UpdatedBy = "test", CancelReason = "", Status = UpdateBookingStatus.Cancelled }; var hearingId = Guid.NewGuid(); _bookingsApiClient.Setup(x => x.UpdateBookingStatusAsync(hearingId, request)) .ThrowsAsync(new BookingsApiException("", StatusCodes.Status500InternalServerError, "", null, null)); Assert.ThrowsAsync <BookingsApiException>(() => _controller.UpdateBookingStatus(hearingId, request)); }
public async Task <IActionResult> ConfirmHearingById(Guid hearingId, UpdateBookingStatusRequest request) { _logger.LogDebug($"ConfirmHearingById {hearingId}"); try { var response = await _testApiClient.ConfirmHearingByIdAsync(hearingId, request); _logger.LogDebug("Hearing confirmed with id {id}", response.Id); return(Created(nameof(ConfirmHearingById), response)); } catch (TestApiException e) { _logger.LogError(e, "Unable to confirm hearing with error '{message}'", e.Message); return(StatusCode(e.StatusCode, e.Response)); } }
private ConferenceDetailsResponse CreateConference() { var vho = _c.Users.First(x => x.UserType == UserType.VideoHearingsOfficer); var request = new UpdateBookingStatusRequest() { UpdatedBy = vho.Username, CancelReason = null, Status = UpdateBookingStatus.Created }; var response = _c.Api.ConfirmHearingToCreateConference(_c.Test.HearingResponse.Id, request); response.StatusCode.Should().Be(HttpStatusCode.Created); var conference = RequestHelper.Deserialise <ConferenceDetailsResponse>(response.Content); NUnit.Framework.TestContext.WriteLine($"Conference created with Conference Id {conference.Id}"); return(conference); }
public async Task Should_change_hearing_status_to_failed() { var request = new UpdateBookingStatusRequest { UpdatedBy = "*****@*****.**", Status = UpdateBookingStatus.Failed, CancelReason = "" }; var hearingId = Guid.NewGuid(); CommandHandlerMock.Setup(x => x.Handle(It.IsAny <UpdateHearingStatusCommand>())); var result = await Controller.UpdateBookingStatus(hearingId, request); result.Should().NotBeNull(); var objectResult = (NoContentResult)result; objectResult.StatusCode.Should().Be((int)HttpStatusCode.NoContent); CommandHandlerMock.Verify(c => c.Handle(It.IsAny <UpdateHearingStatusCommand>()), Times.Once); }
public async Task UpdateBookingStatus_returns_success_response_when_status_not_failed() { _userIdentity.Setup(x => x.GetUserIdentityName()).Returns("test"); var request = new UpdateBookingStatusRequest { UpdatedBy = "test", CancelReason = "", Status = UpdateBookingStatus.Failed }; var hearingId = Guid.NewGuid(); _bookingsApiClient.Setup(x => x.UpdateBookingStatusAsync(hearingId, request)); var response = await _controller.UpdateBookingStatus(hearingId, request); var result = (OkObjectResult)response; result.StatusCode.Should().Be(StatusCodes.Status200OK); result.Value.Should().NotBeNull().And.BeAssignableTo <UpdateBookingStatusResponse>().Subject.Success.Should().BeTrue(); _bookingsApiClient.Verify(x => x.UpdateBookingStatusAsync(hearingId, request), Times.Once); }
public void CreateConference() { var vho = _c.Test.Users.First(x => x.User_type == UserType.VideoHearingsOfficer); var request = new UpdateBookingStatusRequest() { Updated_by = vho.Username, AdditionalProperties = null, Cancel_reason = null, Status = UpdateBookingStatus.Created }; var response = _c.Apis.TestApi.ConfirmHearingToCreateConference(_c.Test.NewHearingId, request); response.StatusCode.Should().Be(HttpStatusCode.Created); var conference = RequestHelper.Deserialise <ConferenceDetailsResponse>(response.Content); _c.Test.Conference = conference; _c.Test.Conferences.Add(conference); _c.Test.NewConferenceId = conference.Id; _c.Test.ConferenceParticipants = conference.Participants; NUnit.Framework.TestContext.WriteLine($"Conference created with Conference Id {conference.Id}"); }
public async Task <IActionResult> ConfirmHearingById(Guid hearingId, UpdateBookingStatusRequest request) { _logger.LogDebug("ConfirmHearingById {hearingId}", hearingId); try { await _bookingsApiClient.GetHearingDetailsByIdAsync(hearingId); } catch (BookingsApiException e) { return(StatusCode(e.StatusCode, e.Response)); } _logger.LogDebug("Hearing with id {hearingId} retrieved", hearingId); try { await _bookingsApiService.UpdateBookingStatusPolling(hearingId, request); } catch (BookingsApiException e) { return(StatusCode(e.StatusCode, e.Response)); } _logger.LogInformation("Successfully confirmed hearing with id {hearingId}", hearingId); try { var response = await _videoApiService.GetConferenceByHearingIdPolling(hearingId); return(Created(nameof(ConfirmHearingById), response)); } catch (VideoApiException e) { return(StatusCode(e.StatusCode, e.Response)); } }
public async Task UpdateBookingStatus_returns_success_response_when_conference_exists_with_meeting_room_and_send_reminder_email() { _userIdentity.Setup(x => x.GetUserIdentityName()).Returns("test"); var request = new UpdateBookingStatusRequest { UpdatedBy = "test", CancelReason = "", Status = UpdateBookingStatus.Created }; var hearingId = Guid.NewGuid(); var hearing = InitBookingForResponse(hearingId); hearing.OtherInformation = new OtherInformationDetails { JudgeEmail = "*****@*****.**", JudgePhone = "12345789", OtherInformation = "info" }.ToOtherInformationString(); _bookingsApiClient.Setup(x => x.GetHearingDetailsByIdAsync(It.IsAny <Guid>())) .ReturnsAsync(hearing); var expectedConferenceDetailsResponse = new ConferenceDetailsResponse { Id = Guid.NewGuid(), HearingId = hearingId, MeetingRoom = new MeetingRoomResponse { AdminUri = "admin", JudgeUri = "judge", ParticipantUri = "participant", PexipNode = "pexip", TelephoneConferenceId = "121212" } }; _bookingsApiClient.Setup(x => x.UpdateBookingStatusAsync(hearingId, request)); _pollyRetryServiceMock.Setup(x => x.WaitAndRetryAsync <VideoApiException, ConferenceDetailsResponse> ( It.IsAny <int>(), It.IsAny <Func <int, TimeSpan> >(), It.IsAny <Action <int> >(), It.IsAny <Func <ConferenceDetailsResponse, bool> >(), It.IsAny <Func <Task <ConferenceDetailsResponse> > >() )) .Callback(async(int retries, Func <int, TimeSpan> sleepDuration, Action <int> retryAction, Func <ConferenceDetailsResponse, bool> handleResultCondition, Func <Task <ConferenceDetailsResponse> > executeFunction) => { sleepDuration(1); retryAction(1); handleResultCondition(expectedConferenceDetailsResponse); await executeFunction(); }) .ReturnsAsync(expectedConferenceDetailsResponse); _bookingsApiClient.Setup(x => x.GetHearingsByGroupIdAsync(hearing.GroupId.Value)).ReturnsAsync(new List <HearingDetailsResponse> { hearing }); var response = await _controller.UpdateBookingStatus(hearingId, request); var result = (OkObjectResult)response; result.StatusCode.Should().Be(StatusCodes.Status200OK); result.Value.Should().NotBeNull().And.BeAssignableTo <UpdateBookingStatusResponse>().Subject.Success.Should().BeTrue(); result.Value.Should().NotBeNull().And.BeAssignableTo <UpdateBookingStatusResponse>().Subject.TelephoneConferenceId.Should().Be("121212"); _bookingsApiClient.Verify(x => x.UpdateBookingStatusAsync(hearingId, request), Times.Once); _pollyRetryServiceMock.Verify(x => x.WaitAndRetryAsync <VideoApiException, ConferenceDetailsResponse> ( It.IsAny <int>(), It.IsAny <Func <int, TimeSpan> >(), It.IsAny <Action <int> >(), It.IsAny <Func <ConferenceDetailsResponse, bool> >(), It.IsAny <Func <Task <ConferenceDetailsResponse> > >() ), Times.AtLeastOnce); _notificationApiMock.Verify( x => x.CreateNewNotificationAsync(It.Is <AddNotificationRequest>(notification => notification.NotificationType == NotificationType.HearingReminderJoh)), Times.AtLeast(1)); _notificationApiMock.Verify( x => x.CreateNewNotificationAsync(It.Is <AddNotificationRequest>(notification => notification.NotificationType == NotificationType.HearingReminderLip)), Times.AtLeast(1)); _notificationApiMock.Verify( x => x.CreateNewNotificationAsync(It.Is <AddNotificationRequest>(notification => notification.NotificationType == NotificationType.HearingReminderRepresentative)), Times.AtLeast(1)); _notificationApiMock.Verify( x => x.CreateNewNotificationAsync(It.Is <AddNotificationRequest>(notification => notification.NotificationType == NotificationType.HearingConfirmationJudge)), Times.AtLeast(1)); }
public async Task UpdateBookingStatus_returns_false_response_when_conference_exists_but_admin_uri_null() { _userIdentity.Setup(x => x.GetUserIdentityName()).Returns("test"); var updateCreatedStatus = new UpdateBookingStatusRequest { UpdatedBy = "test", CancelReason = "", Status = UpdateBookingStatus.Created }; var hearingId = Guid.NewGuid(); var expectedConferenceDetailsResponse = new ConferenceDetailsResponse { Id = Guid.NewGuid(), HearingId = hearingId, MeetingRoom = new MeetingRoomResponse { JudgeUri = "judge", ParticipantUri = "participant", PexipNode = "pexip" } }; _bookingsApiClient.Setup(x => x.UpdateBookingStatusAsync(hearingId, updateCreatedStatus)); _bookingsApiClient.Setup(x => x.UpdateBookingStatusAsync(hearingId, It.IsAny <UpdateBookingStatusRequest>())); _pollyRetryServiceMock.Setup(x => x.WaitAndRetryAsync <VideoApiException, ConferenceDetailsResponse> ( It.IsAny <int>(), It.IsAny <Func <int, TimeSpan> >(), It.IsAny <Action <int> >(), It.IsAny <Func <ConferenceDetailsResponse, bool> >(), It.IsAny <Func <Task <ConferenceDetailsResponse> > >() )) .Callback(async(int retries, Func <int, TimeSpan> sleepDuration, Action <int> retryAction, Func <ConferenceDetailsResponse, bool> handleResultCondition, Func <Task <ConferenceDetailsResponse> > executeFunction) => { sleepDuration(1); retryAction(1); handleResultCondition(expectedConferenceDetailsResponse); await executeFunction(); }) .ThrowsAsync(new VideoApiException("", 0, "", null, null)); var response = await _controller.UpdateBookingStatus(hearingId, updateCreatedStatus); var result = (OkObjectResult)response; result.StatusCode.Should().Be(StatusCodes.Status200OK); var updateBookingStatusResp = (UpdateBookingStatusResponse)result.Value; updateBookingStatusResp.Should().NotBeNull(); updateBookingStatusResp.Success.Should().BeFalse(); updateBookingStatusResp.Message.Should().Be($"Failed to get the conference from video api, possibly the conference was not created or the kinly meeting room is null - hearingId: {hearingId}"); _bookingsApiClient.Verify(x => x.UpdateBookingStatusAsync(hearingId, updateCreatedStatus), Times.Once); _bookingsApiClient.Verify(x => x.UpdateBookingStatusAsync(hearingId, It.Is <UpdateBookingStatusRequest>(b => b.Status == UpdateBookingStatus.Failed && b.UpdatedBy == "System" && b.CancelReason == string.Empty )), Times.Once); _pollyRetryServiceMock.Verify(x => x.WaitAndRetryAsync <VideoApiException, ConferenceDetailsResponse> ( It.IsAny <int>(), It.IsAny <Func <int, TimeSpan> >(), It.IsAny <Action <int> >(), It.IsAny <Func <ConferenceDetailsResponse, bool> >(), It.IsAny <Func <Task <ConferenceDetailsResponse> > >() ), Times.AtLeastOnce); }
public UpdateBookingStatusRequestBuilder() { _request = new UpdateBookingStatusRequest { Status = UpdateBookingStatus.Created }; }
public string UpdateHearingStatus(Guid hearingId, UpdateBookingStatusRequest updateBookingStatusRequest) => $"{ApiRoot}/{hearingId}";
public void OneTimeSetUp() { _validator = new UpdateBookingStatusRequestValidation(); request = new UpdateBookingStatusRequest(); }
public async Task <IActionResult> UpdateBookingStatus(Guid hearingId, UpdateBookingStatusRequest updateBookingStatusRequest) { var errorMessage = $"Failed to get the conference from video api, possibly the conference was not created or the kinly meeting room is null - hearingId: {hearingId}"; try { _logger.LogDebug("Attempting to update hearing {Hearing} to booking status {BookingStatus}", hearingId, updateBookingStatusRequest.Status); updateBookingStatusRequest.UpdatedBy = _userIdentity.GetUserIdentityName(); await _bookingsApiClient.UpdateBookingStatusAsync(hearingId, updateBookingStatusRequest); _logger.LogDebug("Updated hearing {Hearing} to booking status {BookingStatus}", hearingId, updateBookingStatusRequest.Status); if (updateBookingStatusRequest.Status != BookingsApi.Contract.Requests.Enums.UpdateBookingStatus.Created) { return(Ok(new UpdateBookingStatusResponse { Success = true })); } try { _logger.LogDebug("Hearing {Hearing} is confirmed. Polling for Conference in VideoApi", hearingId); var conferenceDetailsResponse = await _hearingsService.GetConferenceDetailsByHearingIdWithRetry(hearingId, errorMessage); _logger.LogInformation("Found conference for hearing {Hearing}", hearingId); if (conferenceDetailsResponse.HasValidMeetingRoom()) { var hearing = await _bookingsApiClient.GetHearingDetailsByIdAsync(hearingId); _logger.LogInformation("Sending a reminder email for hearing {Hearing}", hearingId); await _hearingsService.SendHearingReminderEmail(hearing); return(Ok(new UpdateBookingStatusResponse { Success = true, TelephoneConferenceId = conferenceDetailsResponse.MeetingRoom.TelephoneConferenceId })); } } catch (VideoApiException ex) { _logger.LogError(ex, "Failed to confirm a hearing. {ErrorMessage}", errorMessage); } _logger.LogError("There was an unknown error for hearing {Hearing}. Updating status to failed", hearingId); // Set the booking status to failed as the video api failed await _bookingsApiClient.UpdateBookingStatusAsync(hearingId, new UpdateBookingStatusRequest { Status = BookingsApi.Contract.Requests.Enums.UpdateBookingStatus.Failed, UpdatedBy = "System", CancelReason = string.Empty }); return(Ok(new UpdateBookingStatusResponse { Success = false, Message = errorMessage })); } catch (BookingsApiException e) { if (e.StatusCode == (int)HttpStatusCode.BadRequest) { return(BadRequest(e.Response)); } if (e.StatusCode == (int)HttpStatusCode.NotFound) { return(NotFound(e.Response)); } _logger.LogError(e, "There was an unknown error updating status for hearing {Hearing}", hearingId); throw; } }