Skip to content

Commit

Permalink
VIH-10326 Fix v2 toggle issues (#1305)
Browse files Browse the repository at this point in the history
* Fix v2 toggle issues

* Reinstate api tests

* Update search service

* Added null coalesc for non populated johs

* Check fo null judicary participant before mapping

---------

Co-authored-by: William Craig <[email protected]>
(cherry picked from commit 89f8d85)
  • Loading branch information
oliver-scott authored and will-craig committed Nov 29, 2023
1 parent 78b58d0 commit 2a3c9d0
Show file tree
Hide file tree
Showing 8 changed files with 265 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using AdminWebsite.Configuration;
using System;
using AdminWebsite.Configuration;
using AdminWebsite.Contracts.Responses;
using AdminWebsite.Services;
using AdminWebsite.UnitTests.Helper;
Expand All @@ -8,6 +9,7 @@
using Moq;
using NUnit.Framework;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
Expand Down Expand Up @@ -323,5 +325,96 @@ public void Should_pass_on_exception_request_from_bookings_api_for_judiciary_per
Assert.ThrowsAsync<BookingsApiException>(() => _controller.PostJudiciaryPersonBySearchTermAsync(term));
_bookingsApiClient.Verify(x => x.PostJudiciaryPersonBySearchTermAsync(It.IsAny<SearchTermRequest>()), Times.Once);
}

[Test]
[TestCase(false, false)]
[TestCase(false, true)]
[TestCase(true, false)]
[TestCase(true, true)]
public async Task PostJudgesBySearchTerm_should_return_judiciary_and_courtroom_accounts_if_match_to_search_term(bool withJudiciary, bool withCourtroom)
{
_judiciaryResponse = new List<JudiciaryPersonResponse>
{
new()
{
Email = "[email protected]",
FirstName = "Jack",
LastName = "Mann",
WorkPhone = "",
Title = "Mr",
FullName = "Mr Jack Mann",
PersonalCode = "12345678"
}
};
_bookingsApiClient.Setup(x => x.PostJudiciaryPersonBySearchTermAsync(It.IsAny<SearchTermRequest>()))
.ReturnsAsync(withJudiciary ? _judiciaryResponse : new List<JudiciaryPersonResponse>());

var _courtRoomResponse = new List<JudgeResponse>
{
new JudgeResponse
{
FirstName = "FirstName1",
LastName = "FirstName2",
Email = "[email protected]",
ContactEmail = "[email protected]"
},
new JudgeResponse
{
FirstName = "FirstName3",
LastName = "LastName3",
Email = "[email protected]",
ContactEmail = "[email protected]"
},
new JudgeResponse
{
FirstName = "FirstName2",
LastName = "LastName2",
Email = "[email protected]", // Out of order to test order
ContactEmail = "[email protected]"
}
};

_userAccountService.Setup(x => x.SearchJudgesByEmail(It.IsAny<string>()))
.ReturnsAsync(withCourtroom ? _courtRoomResponse : new List<JudgeResponse>());


var searchTerm = "judici";
var result = await _controller.PostJudgesBySearchTermAsync(searchTerm);

var okRequestResult = (OkObjectResult)result.Result;
okRequestResult.StatusCode.Should().NotBeNull();
var personRespList = (List<JudgeResponse>)okRequestResult.Value;

var expectedJudiciaryCount = withJudiciary ? _judiciaryResponse.Count : 0;
var expectedCourtRoomCount = withCourtroom ? _courtRoomResponse.Count : 0;

var expectedTotal = expectedJudiciaryCount + expectedCourtRoomCount;

personRespList.Count.Should().Be(expectedTotal);
if(!withJudiciary && withCourtroom) // Only courtroom is set up to test order
{
Assert.That(personRespList, Is.EquivalentTo(_courtRoomResponse));
Assert.That(personRespList, Is.Not.EqualTo(_courtRoomResponse));
Assert.That(personRespList, Is.EqualTo(_courtRoomResponse.OrderBy(x => x.Email)));
}
}

[Test]
public async Task PostJudgesBySearchTerm_should_pass_on_bad_request_from_bookings_api_for_judge_accounts()
{
_bookingsApiClient.Setup(x => x.PostJudiciaryPersonBySearchTermAsync(It.IsAny<SearchTermRequest>()))
.ThrowsAsync(ClientException.ForBookingsAPI(HttpStatusCode.BadRequest));

var response = await _controller.PostJudgesBySearchTermAsync("term");
response.Result.Should().BeOfType<BadRequestObjectResult>();
}

[Test]
public void PostJudgesBySearchTerm_should_pass_on_exception_request_from_bookings_api_for_judges_accounts()
{
_bookingsApiClient.Setup(x => x.PostJudiciaryPersonBySearchTermAsync(It.IsAny<SearchTermRequest>()))
.ThrowsAsync(ClientException.ForBookingsAPI(HttpStatusCode.InternalServerError));
Assert.ThrowsAsync<BookingsApiException>(() => _controller.PostJudgesBySearchTermAsync("term"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export class BookingDetailsService {
const judges: Array<ParticipantDetailsModel> = [];
const judicialMembers: Array<JudiciaryParticipantDetailsModel> = [];

const mappedJohs = hearingResponse.judiciary_participants.map(
const mappedJohs = hearingResponse.judiciary_participants?.map(
j =>
new JudiciaryParticipantDetailsModel(
j.title,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1867,6 +1867,114 @@ export class BHClient extends ApiClientBase {
return _observableOf(null as any);
}

/**
* Find judges and court rooms accounts list by email search term.
* @param body (optional) The email address search term.
* @return Success
*/
postJudgesBySearchTerm(body: string | undefined): Observable<JudgeResponse[]> {
let url_ = this.baseUrl + '/api/judiciary/judges';
url_ = url_.replace(/[?&]$/, '');

const content_ = JSON.stringify(body);

let options_: any = {
body: content_,
observe: 'response',
responseType: 'blob',
headers: new HttpHeaders({
'Content-Type': 'application/json-patch+json',
Accept: 'application/json'
})
};

return _observableFrom(this.transformOptions(options_))
.pipe(
_observableMergeMap(transformedOptions_ => {
return this.http.request('post', url_, transformedOptions_);
})
)
.pipe(
_observableMergeMap((response_: any) => {
return this.processPostJudgesBySearchTerm(response_);
})
)
.pipe(
_observableCatch((response_: any) => {
if (response_ instanceof HttpResponseBase) {
try {
return this.processPostJudgesBySearchTerm(response_ as any);
} catch (e) {
return _observableThrow(e) as any as Observable<JudgeResponse[]>;
}
} else return _observableThrow(response_) as any as Observable<JudgeResponse[]>;
})
);
}

protected processPostJudgesBySearchTerm(response: HttpResponseBase): Observable<JudgeResponse[]> {
const status = response.status;
const responseBlob =
response instanceof HttpResponse
? response.body
: (response as any).error instanceof Blob
? (response as any).error
: undefined;

let _headers: any = {};
if (response.headers) {
for (let key of response.headers.keys()) {
_headers[key] = response.headers.get(key);
}
}
if (status === 500) {
return blobToText(responseBlob).pipe(
_observableMergeMap((_responseText: string) => {
let result500: any = null;
let resultData500 = _responseText === '' ? null : JSON.parse(_responseText, this.jsonParseReviver);
result500 = UnexpectedErrorResponse.fromJS(resultData500);
return throwException('Server Error', status, _responseText, _headers, result500);
})
);
} else if (status === 200) {
return blobToText(responseBlob).pipe(
_observableMergeMap((_responseText: string) => {
let result200: any = null;
let resultData200 = _responseText === '' ? null : JSON.parse(_responseText, this.jsonParseReviver);
if (Array.isArray(resultData200)) {
result200 = [] as any;
for (let item of resultData200) result200!.push(JudgeResponse.fromJS(item));
} else {
result200 = <any>null;
}
return _observableOf(result200);
})
);
} else if (status === 400) {
return blobToText(responseBlob).pipe(
_observableMergeMap((_responseText: string) => {
let result400: any = null;
let resultData400 = _responseText === '' ? null : JSON.parse(_responseText, this.jsonParseReviver);
result400 = ProblemDetails.fromJS(resultData400);
return throwException('Bad Request', status, _responseText, _headers, result400);
})
);
} else if (status === 401) {
return blobToText(responseBlob).pipe(
_observableMergeMap((_responseText: string) => {
return throwException('Unauthorized', status, _responseText, _headers);
})
);
} else if (status !== 200 && status !== 204) {
return blobToText(responseBlob).pipe(
_observableMergeMap((_responseText: string) => {
return throwException('An unexpected server error occurred.', status, _responseText, _headers);
})
);
}
return _observableOf(null as any);
}

/**
* Find judiciary person list by email search term.
* @param body (optional) The email address search term.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,15 @@ describe('SearchService', () => {
beforeEach(() => {
clientApiSpy = jasmine.createSpyObj<BHClient>('BHClient', [
'postPersonBySearchTerm',
'searchForJudiciaryPerson',
'postJudiciaryPersonBySearchTerm',
'postJudgesBySearchTerm',
'getStaffMembersBySearchTerm'
]);

clientApiSpy.postPersonBySearchTerm.and.returnValue(of(personList));
clientApiSpy.getStaffMembersBySearchTerm.and.returnValue(of(staffMemberList));
clientApiSpy.searchForJudiciaryPerson.and.returnValue(of(judiciaryPersonList));
clientApiSpy.postJudiciaryPersonBySearchTerm.and.returnValue(of(judgeList));
clientApiSpy.postJudiciaryPersonBySearchTerm.and.returnValue(of(judiciaryPersonList));
clientApiSpy.postJudgesBySearchTerm.and.returnValue(of(judgeList));

launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.eJudFeature).and.returnValue(of(true));

Expand All @@ -166,8 +166,8 @@ describe('SearchService', () => {
beforeEach(() => {
clientApiSpy = jasmine.createSpyObj<BHClient>('BHClient', [
'postPersonBySearchTerm',
'searchForJudiciaryPerson',
'postJudiciaryPersonBySearchTerm',
'postJudgesBySearchTerm',
'getStaffMembersBySearchTerm'
]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,14 @@ export class SearchService {
}

searchJudiciaryEntries(term): Observable<Array<PersonResponse>> {
return this.bhClient.searchForJudiciaryPerson(term);
return this.bhClient.postJudiciaryPersonBySearchTerm(term);
}

searchStaffMemberAccounts(term): Observable<Array<PersonResponse>> {
return this.bhClient.getStaffMembersBySearchTerm(term);
}

searchJudgeAccounts(term): Observable<Array<JudgeResponse>> {
return this.bhClient.postJudiciaryPersonBySearchTerm(term);
return this.bhClient.postJudgesBySearchTerm(term);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -217,9 +217,11 @@ export class VideoHearingsService {
hearing.scheduled_date_time = new Date(booking.scheduled_date_time);
hearing.scheduled_duration = booking.scheduled_duration;
hearing.participants = this.mapParticipantModelToEditParticipantRequest(booking.participants);
hearing.judiciary_participants = this.mapJudicialMemberDtoToJudiciaryParticipantRequest(booking.judiciaryParticipants);
hearing.audio_recording_required = booking.audio_recording_required;
hearing.endpoints = this.mapEndpointModelToEditEndpointRequest(booking.endpoints);
if (booking.judiciaryParticipants?.length > 0) {
hearing.judiciary_participants = this.mapJudicialMemberDtoToJudiciaryParticipantRequest(booking.judiciaryParticipants);
}
return hearing;
}

Expand Down Expand Up @@ -326,7 +328,7 @@ export class VideoHearingsService {
hearing.status = response.status;
hearing.audio_recording_required = response.audio_recording_required;
hearing.endpoints = this.mapEndpointResponseToEndpointModel(response.endpoints, response.participants);
hearing.judiciaryParticipants = response.judiciary_participants.map(judiciaryParticipant =>
hearing.judiciaryParticipants = response.judiciary_participants?.map(judiciaryParticipant =>
JudicialMemberDto.fromJudiciaryParticipantResponse(judiciaryParticipant)
);
hearing.isConfirmed = Boolean(response.confirmed_date);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,46 @@ public JudiciaryAccountsController(IUserAccountService userAccountService, JavaS
_bookingsApiClient = bookingsApiClient;
_testSettings = testSettings.Value;
}

/// <summary>
/// Find judges and court rooms accounts list by email search term.
/// </summary>
/// <param name = "term" > The email address search term.</param>
/// <returns> The list of judges</returns>
[HttpPost("judges", Name = "PostJudgesBySearchTerm")]
[SwaggerOperation(OperationId = "PostJudgesBySearchTerm")]
[ProducesResponseType(typeof(List<JudgeResponse>), (int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
public async Task<ActionResult<IList<JudgeResponse>>> PostJudgesBySearchTermAsync([FromBody] string term)
{
try
{
term = _encoder.Encode(term);
var searchTerm = new SearchTermRequest(term);

var courtRoomJudgesTask = _userAccountService.SearchJudgesByEmail(searchTerm.Term);
var eJudiciaryJudgesTask = GetEjudiciaryJudgesBySearchTermAsync(searchTerm);

await Task.WhenAll(courtRoomJudgesTask, eJudiciaryJudgesTask);

var courtRoomJudges = await courtRoomJudgesTask;
var eJudiciaryJudges = (await eJudiciaryJudgesTask).Select(x => JudgeResponseMapper.MapTo(x));

var allJudges = courtRoomJudges.Concat(eJudiciaryJudges)
.OrderBy(x => x.Email).Take(20).ToList();

return Ok(allJudges);
}
catch (BookingsApiException e)
{
if (e.StatusCode == (int)HttpStatusCode.BadRequest)
{
return BadRequest(e.Response);
}

throw;
}
}

/// <summary>
/// Find judiciary person list by email search term.
Expand Down
12 changes: 12 additions & 0 deletions AdminWebsite/AdminWebsite/Mappers/JudgeResponseMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,17 @@ public static JudgeResponse MapTo(JudgeResponse personResponse)
};

}

public static JudgeResponse MapTo(PersonResponse personResponse)
{
return new JudgeResponse
{
FirstName = personResponse.FirstName,
LastName = personResponse.LastName,
Email = personResponse.Username,
AccountType = JudgeAccountType.Judiciary,
ContactEmail = personResponse.ContactEmail
};
}
}
}

0 comments on commit 2a3c9d0

Please sign in to comment.