From aa9112bdaf4b63ceb93142785b2e0249266eccd3 Mon Sep 17 00:00:00 2001 From: marcogagliardi Date: Mon, 10 Jun 2024 08:03:02 +0100 Subject: [PATCH 01/25] removed feature flag: Book_and_confirm, vho-work-allocation, notify-post-may-2023-templates, --- .../HearingsController/BookNewHearingTests.cs | 1 - .../HearingsController/EditHearingTests.cs | 1 - .../HearingsController/FailHearingTests.cs | 1 - .../GetStatusHearingTests.cs | 53 ----- .../HearingsController/PostHearingTests.cs | 1 - .../Services/HearingServiceTests.cs | 3 +- .../ClientApp/src/app/app-routing.module.ts | 3 +- .../ClientApp/src/app/app.module.ts | 2 - .../add-participant.component.spec.ts | 11 -- .../add-participant.component.ts | 61 ++---- .../assign-judge.component.spec.ts | 14 +- .../assign-judge/assign-judge.component.ts | 20 +- .../breadcrumb/breadcrumb.component.spec.ts | 11 -- .../breadcrumb/breadcrumb.component.ts | 23 +-- .../bookings-list.component.html | 7 +- .../bookings-list.component.spec.ts | 182 ------------------ .../bookings-list/bookings-list.component.ts | 58 ++---- .../hearing-details.component.spec.ts | 36 +--- .../hearing-details.component.ts | 18 +- .../app/dashboard/dashboard.component.spec.ts | 31 --- .../src/app/dashboard/dashboard.component.ts | 38 ++-- .../work-allocation-feature.guard.spec.ts | 41 ---- .../guards/work-allocation-feature.guard.ts | 25 --- .../src/app/services/launch-darkly.service.ts | 2 - .../Configuration/FeatureToggles.cs | 21 -- .../Controllers/HearingsController.cs | 3 +- 26 files changed, 64 insertions(+), 603 deletions(-) delete mode 100644 AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/work-allocation-feature.guard.spec.ts delete mode 100644 AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/work-allocation-feature.guard.ts diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/BookNewHearingTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/BookNewHearingTests.cs index 83f910067..8950585b6 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/BookNewHearingTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/BookNewHearingTests.cs @@ -47,7 +47,6 @@ public void Setup() TelephoneConferenceId = "expected_conference_phone_id" } }); - _mocker.Mock().Setup(x => x.BookAndConfirmToggle()).Returns(true); _controller = _mocker.Create(); } diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditHearingTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditHearingTests.cs index d16248841..b98fb816b 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditHearingTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditHearingTests.cs @@ -66,7 +66,6 @@ public void Setup() _editHearingRequestValidator = new Mock>(); _conferencesServiceMock = new Mock(); _featureToggle = new Mock(); - _featureToggle.Setup(e => e.BookAndConfirmToggle()).Returns(true); _conferencesServiceMock.Setup(cs => cs.GetConferenceDetailsByHearingId(It.IsAny(), false)) .ReturnsAsync(new ConferenceDetailsResponse { diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/FailHearingTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/FailHearingTests.cs index 35a6dc790..1b61dec19 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/FailHearingTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/FailHearingTests.cs @@ -48,7 +48,6 @@ public void Setup() new ParticipantResponse {HearingRoleName = "Judge"} } }); - _mocker.Mock().Setup(e => e.BookAndConfirmToggle()).Returns(true); _controller = _mocker.Create(); } diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetStatusHearingTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetStatusHearingTests.cs index 63ba8f9e8..173dc79d1 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetStatusHearingTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetStatusHearingTests.cs @@ -296,59 +296,6 @@ public async Task Should_return_ok_status_with_success_when_V2flag_on() } - [TestCase(false)] - [TestCase(true)] - public async Task Should_return_ok_status_with_success_when_users_not_created_for_successful_multi_day_booking_with_notify_flag_on(bool v2FlagOn) - { - // When the notify flag is enabled, users for multi day bookings are created as part of the clone process rather than the first day of the multi-day, - // so don't wait for them to be created - - // Arrange - _featureFlag.Setup(x => x.UsePostMay2023Template()).Returns(true); - _featureFlag.Setup(x => x.UseV2Api()).Returns(v2FlagOn); - - if (v2FlagOn) - { - _vhExistingHearingV2.GroupId = _vhExistingHearingV2.Id; // Multi day hearing - _vhExistingHearingV2.Status = BookingStatusV2.Created; - } - else - { - _vhExistingHearing.GroupId = _vhExistingHearing.Id; // Multi day hearing - _vhExistingHearing.Status = BookingStatus.Created; - } - - foreach (var participant in _vhExistingHearing.Participants) - { - // Contact email is same as username, so user not created - participant.Username = participant.ContactEmail; - } - - // Indicate a successful booking - var conferenceResponse = new ConferenceDetailsResponse - { - MeetingRoom = new() - { - AdminUri = "AdminUri", - ParticipantUri = "ParticipantUri", - JudgeUri = "JudgeUri", - PexipNode = "PexipNode" - } - }; - _conferenceDetailsServiceMock.Setup(x => x.GetConferenceDetailsByHearingId(_guid, false)) - .ReturnsAsync(conferenceResponse); - - // Act - var result = await _controller.GetHearingConferenceStatus(_guid); - - // Assert - var okRequestResult = (OkObjectResult)result; - okRequestResult.StatusCode.Should().Be(200); - - var hearing = (UpdateBookingStatusResponse)((OkObjectResult)result).Value; - hearing.Success.Should().Be(true); - } - private HearingDetailsResponseV2 GetHearingDetailsResponseV2(BookingsApi.Contract.V2.Enums.BookingStatusV2 status) { _guid = Guid.NewGuid(); diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/PostHearingTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/PostHearingTests.cs index c0196403b..ef1c743fc 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/PostHearingTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/PostHearingTests.cs @@ -54,7 +54,6 @@ public void Setup() }, CaseTypeName = "Generic" }); - _mocker.Mock().Setup(e => e.BookAndConfirmToggle()).Returns(true); _controller = _mocker.Create(); } diff --git a/AdminWebsite/AdminWebsite.UnitTests/Services/HearingServiceTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Services/HearingServiceTests.cs index 98a445fe0..2d3ac80d1 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Services/HearingServiceTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Services/HearingServiceTests.cs @@ -47,8 +47,7 @@ public void Setup() _mocker.Mock() .Setup(c => c.GetHearingsByGroupIdAsync(It.IsAny())) .ReturnsAsync(new List { _hearing }); - _mocker.Mock() - .Setup(x => x.BookAndConfirmToggle()).Returns(true); + _service = _mocker.Create(); _hearing = InitHearing(); } diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/app-routing.module.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/app-routing.module.ts index c7e6348fc..522f37899 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/app-routing.module.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/app-routing.module.ts @@ -12,7 +12,6 @@ import { EditParticipantSearchComponent } from './edit-participant/edit-particip import { EditParticipantComponent } from './edit-participant/edit-participant/edit-participant.component'; import { HomeComponent } from './home/home.component'; import { AdminGuard } from './security/guards/admin.guard'; -import { WorkAllocationFeatureGuard } from './security/guards/work-allocation-feature.guard'; import { VhOfficerAdminGuard } from './security/guards/vh-officer-admin.guard'; import { LoginComponent } from './security/login.component'; import { ReformLoginComponent } from './security/reform-login.component'; @@ -38,7 +37,7 @@ export const routes: Routes = [ { path: 'edit-participant', component: EditParticipantComponent, canActivate: [AuthGuard, AdminGuard] }, { path: 'work-allocation', - canActivate: [AuthGuard, VhOfficerAdminGuard, WorkAllocationFeatureGuard], + canActivate: [AuthGuard, VhOfficerAdminGuard], loadChildren: () => import('./work-allocation/work-allocation.module').then(m => m.WorkAllocationModule) }, { diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/app.module.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/app.module.ts index f8977088c..2ffefec7f 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/app.module.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/app.module.ts @@ -36,7 +36,6 @@ import { AuthConfigModule } from './security/auth-config.module'; import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; import { UnallocatedHearingsComponent } from './dashboard/unallocated-hearings/unallocated-hearings.component'; import { HomeComponent } from './home/home.component'; -import { WorkAllocationFeatureGuard } from './security/guards/work-allocation-feature.guard'; import { VhOfficerAdminGuard } from './security/guards/vh-officer-admin.guard'; import { LastMinuteAmendmentsGuard } from './security/guards/last-minute-amendments.guard'; import { AdminGuard } from './security/guards/admin.guard'; @@ -101,7 +100,6 @@ export function loadConfig(configService: ConfigService) { PageTrackerService, AppInsightsLogger, WindowRef, - WorkAllocationFeatureGuard, ManageTeamFeatureGuard, AudioSearchGuard ], diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/add-participant/add-participant.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/add-participant/add-participant.component.spec.ts index 1a9001a5b..54ba052db 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/add-participant/add-participant.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/add-participant/add-participant.component.spec.ts @@ -290,7 +290,6 @@ describe('AddParticipantComponent', () => { 'removeParticipant', 'mapParticipantHearingRoles' ]); - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.useV2Api).and.returnValue(of(false)); participantServiceSpy.mapParticipantsRoles.and.returnValue(partyList); participantServiceSpy.mapParticipantHearingRoles.and.returnValue(mappedHearingRoles); bookingServiceSpy = jasmine.createSpyObj(['isEditMode', 'resetEditMode']); @@ -524,7 +523,6 @@ describe('AddParticipantComponent', () => { companyName.setValue('CC'); component.isRoleSelected = true; component.isPartySelected = true; - component.referenceDataFeatureFlag = false; component.participantDetails = participant; }); @@ -572,15 +570,6 @@ describe('AddParticipantComponent', () => { const addedParticipant = component.hearing.participants[0]; expect(addedParticipant.addedDuringHearing).toBe(false); }); - it('should add interpreter to role list after saving with reference data flag on', fakeAsync(async () => { - component.hearing.participants = []; - component.referenceDataFeatureFlag = true; - component.ngAfterViewInit(); - tick(600); - component.saveParticipant(); - expect(component.hearingRoleList).toContain('Interpreter'); - flush(); - })); }); it('press button cancel display pop up confirmation dialog', () => { component.addParticipantCancel(); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/add-participant/add-participant.component.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/add-participant/add-participant.component.ts index 19ee13b9c..8a7a8431e 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/add-participant/add-participant.component.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/add-participant/add-participant.component.ts @@ -28,7 +28,6 @@ import { FeatureFlags, LaunchDarklyService } from 'src/app/services/launch-darkl export class AddParticipantComponent extends AddParticipantBaseDirective implements OnInit, AfterViewInit, AfterContentInit, OnDestroy { constants = Constants; - notFound: boolean; titleList: IDropDownModel[] = []; roleList: string[]; selectedParticipantEmail: string = null; @@ -40,12 +39,8 @@ export class AddParticipantComponent extends AddParticipantBaseDirective impleme showConfirmationRemoveParticipant = false; removerFullName: string; localEditMode = false; - isExistingHearing: boolean; - isAnyParticipants: boolean; - existingPerson: boolean; bookingHasParticipants: boolean; $subscriptions: Subscription[] = []; - referenceDataFeatureFlag = false; destroyed$ = new Subject(); interpreteeList: ParticipantModel[] = []; @@ -70,12 +65,6 @@ export class AddParticipantComponent extends AddParticipantBaseDirective impleme } ngOnInit() { - this.launchDarklyService - .getFlag(FeatureFlags.useV2Api) - .pipe(takeUntil(this.destroyed$)) - .subscribe(flag => { - this.referenceDataFeatureFlag = flag; - }); this.checkForExistingRequest(); this.initialiseForm(); super.ngOnInit(); @@ -117,27 +106,17 @@ export class AddParticipantComponent extends AddParticipantBaseDirective impleme setTimeout(() => { const self = this; - const caseTypeIdentifier = this.referenceDataFeatureFlag ? this.hearing.case_type_service_id : this.hearing.case_type; + const caseTypeIdentifier = this.hearing.case_type_service_id; this.logger.debug(`${this.loggerPrefix} Getting participant roles.`); - if (this.referenceDataFeatureFlag) { - this.videoHearingService - .getHearingRoles() - .then((data: HearingRoleResponse[]) => { - self.setupRolesWithoutCaseRole(data); - self.removePartyValidators(); - self.handleRoleSetupForEditMode(self); - }) - .catch(error => this.logger.error(`${this.loggerPrefix} Error getting hearing roles.`, error)); - } else { - this.videoHearingService - .getParticipantRoles(caseTypeIdentifier) - .then((data: CaseAndHearingRolesResponse[]) => { - self.setupRoles(data); - self.handleRoleSetupForEditMode(self); - }) - .catch(error => this.logger.error(`${this.loggerPrefix} Error to get participant case and hearing roles.`, error)); - } + this.videoHearingService + .getHearingRoles() + .then((data: HearingRoleResponse[]) => { + self.setupRolesWithoutCaseRole(data); + self.removePartyValidators(); + self.handleRoleSetupForEditMode(self); + }) + .catch(error => this.logger.error(`${this.loggerPrefix} Error getting hearing roles.`, error)); }, 500); } @@ -364,10 +343,8 @@ export class AddParticipantComponent extends AddParticipantBaseDirective impleme }); this.participantDetails = null; this.clearForm(); - if (this.referenceDataFeatureFlag) { - // Refresh the list in case an interpreter can now be added - this.setupHearingRolesWithoutCaseRole(); - } + // Refresh the list in case an interpreter can now be added + this.setupHearingRolesWithoutCaseRole(); this.displayNext(); this.form.markAsPristine(); this.showDetails = false; @@ -472,13 +449,9 @@ export class AddParticipantComponent extends AddParticipantBaseDirective impleme newParticipant.phone = this.phone.value; newParticipant.title = this.title.value === this.constants.PleaseSelect ? null : this.title.value; newParticipant.case_role_name = this.party.value; - if (this.referenceDataFeatureFlag) { - newParticipant.case_role_name = null; - } + newParticipant.case_role_name = null; newParticipant.hearing_role_name = this.role.value; - if (this.referenceDataFeatureFlag) { - newParticipant.hearing_role_code = this.hearingRoles.find(h => h.name === this.role.value)?.code; - } + newParticipant.hearing_role_code = this.hearingRoles.find(h => h.name === this.role.value)?.code; newParticipant.email = this.searchEmail ? this.searchEmail.email : ''; newParticipant.display_name = this.displayName.value; if (this.isRoleRepresentative(this.role.value, this.party.value)) { @@ -496,13 +469,7 @@ export class AddParticipantComponent extends AddParticipantBaseDirective impleme } private getUserRoleName(newParticipant: ParticipantModel): string { - if (this.referenceDataFeatureFlag) { - return this.hearingRoles.find(h => h.name === newParticipant.hearing_role_name)?.userRole; - } else { - return this.caseAndHearingRoles - .find(c => c.name === newParticipant.case_role_name) - ?.hearingRoles.find(h => h.name === newParticipant.hearing_role_name)?.userRole; - } + return this.hearingRoles.find(h => h.name === newParticipant.hearing_role_name)?.userRole; } private addUpdateLinkedParticipant(newParticipant: ParticipantModel): LinkedParticipantModel[] { diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/assign-judge/assign-judge.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/assign-judge/assign-judge.component.spec.ts index 4bbf633b0..c1d793fd5 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/assign-judge/assign-judge.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/assign-judge/assign-judge.component.spec.ts @@ -25,7 +25,6 @@ import { PageUrls } from 'src/app/shared/page-url.constants'; import { SearchEmailComponent } from '../search-email/search-email.component'; import { MockComponent } from 'ng-mocks'; import { Constants } from 'src/app/common/constants'; -import { FeatureFlags, LaunchDarklyService } from 'src/app/services/launch-darkly.service'; function initHearingRequest(): HearingModel { const participants: ParticipantModel[] = []; @@ -74,7 +73,6 @@ let videoHearingsServiceSpy: jasmine.SpyObj; let judgeDataServiceSpy: jasmine.SpyObj; let routerSpy: jasmine.SpyObj; let bookingServiseSpy: jasmine.SpyObj; -const launchDarklyServiceSpy = jasmine.createSpyObj('LaunchDarklyService', ['getFlag']); let loggerSpy: jasmine.SpyObj; let emailValidationServiceSpy: jasmine.SpyObj; const configSettings = new ClientSettingsResponse(); @@ -103,7 +101,6 @@ describe('AssignJudgeComponent', () => { videoHearingsServiceSpy.getCurrentRequest.and.returnValue(newHearing); emailValidationServiceSpy.validateEmail.and.returnValue(true); emailValidationServiceSpy.hasCourtroomAccountPattern.and.returnValue(true); - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.useV2Api).and.returnValue(of(false)); bookingServiseSpy = jasmine.createSpyObj('BookingService', ['resetEditMode', 'isEditMode', 'removeEditMode']); @@ -119,7 +116,6 @@ describe('AssignJudgeComponent', () => { { provide: JudgeDataService, useValue: judgeDataServiceSpy }, { provide: EmailValidationService, useValue: emailValidationServiceSpy }, { provide: ConfigService, useValue: configServiceSpy }, - { provide: LaunchDarklyService, useValue: launchDarklyServiceSpy }, { provide: Router, useValue: { @@ -560,7 +556,6 @@ describe('AssignJudgeComponent', () => { const updatedJudgeDisplayName = 'UpdatedJudgeDisplayName'; videoHearingsServiceSpy.canAddJudge.and.returnValue(true); component.judge.display_name = updatedJudgeDisplayName; - component.useV2Api = false; }); it('should add judge account when none present', () => { @@ -571,9 +566,6 @@ describe('AssignJudgeComponent', () => { component.hearing.participants.unshift(alternateJudge); }); - it('should add update judge when reference data flag is on', () => { - component.useV2Api = true; - }); afterEach(() => { component.updateJudge(judge); expect(videoHearingsServiceSpy.canAddJudge).toHaveBeenCalledWith(judge.username); @@ -583,10 +575,8 @@ describe('AssignJudgeComponent', () => { expect(component.courtAccountJudgeEmail).toEqual(judge.username); expect(component.judgeDisplayNameFld.value).toEqual(judge.display_name); expect(updatedJudges[0]).toBe(judge); - if (component.useV2Api) { - expect(updatedJudges[0].case_role_name).toBeNull(); - expect(updatedJudges[0].hearing_role_code).toBe(Constants.HearingRoleCodes.Judge); - } + expect(updatedJudges[0].case_role_name).toBeNull(); + expect(updatedJudges[0].hearing_role_code).toBe(Constants.HearingRoleCodes.Judge); expect(component.canNavigate).toBe(true); expect(component.isJudgeParticipantError).toBe(false); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/assign-judge/assign-judge.component.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/assign-judge/assign-judge.component.ts index 8555fde90..fccc5d836 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/assign-judge/assign-judge.component.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/assign-judge/assign-judge.component.ts @@ -16,7 +16,6 @@ import { PipeStringifierService } from '../../services/pipe-stringifier.service' import { EmailValidationService } from 'src/app/booking/services/email-validation.service'; import { ConfigService } from '../../services/config.service'; import { map, takeUntil } from 'rxjs/operators'; -import { FeatureFlags, LaunchDarklyService } from 'src/app/services/launch-darkly.service'; @Component({ selector: 'app-assign-judge', templateUrl: './assign-judge.component.html', @@ -29,8 +28,6 @@ export class AssignJudgeComponent extends BookingBaseComponent implements OnInit judge: ParticipantModel; otherInformationDetails: OtherInformationModel; showAddStaffMemberFld: FormControl; - isStaffMemberValid = false; - showStaffMemberErrorSummary = false; isStaffMemberExisting = false; judgeDisplayNameFld: FormControl; judgeEmailFld: FormControl; @@ -49,7 +46,6 @@ export class AssignJudgeComponent extends BookingBaseComponent implements OnInit invalidPattern: string; isValidEmail = true; showStaffMemberFeature: boolean; - useV2Api = false; destroyed$ = new Subject(); constructor( @@ -60,20 +56,12 @@ export class AssignJudgeComponent extends BookingBaseComponent implements OnInit private pipeStringifier: PipeStringifierService, protected logger: Logger, private emailValidationService: EmailValidationService, - private configService: ConfigService, - private launchDarklyService: LaunchDarklyService + private configService: ConfigService ) { super(bookingService, router, hearingService, logger); } ngOnInit() { - this.launchDarklyService - .getFlag(FeatureFlags.useV2Api) - .pipe(takeUntil(this.destroyed$)) - .subscribe(enabled => { - this.useV2Api = enabled; - }); - this.failedSubmission = false; this.checkForExistingRequest(); this.initForm(); @@ -362,10 +350,8 @@ export class AssignJudgeComponent extends BookingBaseComponent implements OnInit if (this.hearingService.canAddJudge(judge.username)) { judge.is_judge = true; judge.case_role_name = 'Judge'; - if (this.useV2Api) { - judge.case_role_name = null; - judge.hearing_role_code = Constants.HearingRoleCodes.Judge; - } + judge.case_role_name = null; + judge.hearing_role_code = Constants.HearingRoleCodes.Judge; judge.hearing_role_name = 'Judge'; this.hearing.participants = this.hearing.participants.filter(x => !x.is_judge); this.hearing.participants.unshift(judge); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/breadcrumb/breadcrumb.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/breadcrumb/breadcrumb.component.spec.ts index 6008cc4b5..6d33ae71a 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/breadcrumb/breadcrumb.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/breadcrumb/breadcrumb.component.spec.ts @@ -22,7 +22,6 @@ describe('BreadcrumbComponent', () => { beforeEach(() => { launchDarklyServiceSpy = jasmine.createSpyObj('LaunchDarklyService', ['getFlag']); - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.useV2Api).and.returnValue(of(false)); component = new BreadcrumbComponent(router, videoHearingsServiceSpy, launchDarklyServiceSpy); component.breadcrumbItems = BreadcrumbItems.slice(); component.canNavigate = true; @@ -93,12 +92,6 @@ describe('BreadcrumbComponent', () => { expect(router.navigate).toHaveBeenCalledTimes(0); }); - it('should set the breadcrumb name for assign-judge as Judge when staff member feature is OFF', () => { - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.useV2Api).and.returnValue(of(false)); - component.ngOnInit(); - expect(component.breadcrumbItems.find(b => b.Url === PageUrls.AssignJudge).Name).toBe('Judge'); - }); - it('should navigate to next route if canNavigate set to true and next item in correct order', () => { component.canNavigate = true; const step = new BreadcrumbItemModel(2, false, 'Hearing schedule', '/assign-judge', false, false); @@ -113,10 +106,6 @@ describe('BreadcrumbComponent', () => { expect(router.navigate).toHaveBeenCalledWith(['/assign-judge']); }); - it('should set addJudiciaryMemberFlag when ngOnInit is called', () => { - expect(component.addJudiciaryMemberFlag).toBe(false); - }); - it('should unsubscribe from subscriptions when ngOnDestroy is called', () => { spyOn(component.destroyed$, 'next'); spyOn(component.destroyed$, 'complete'); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/breadcrumb/breadcrumb.component.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/breadcrumb/breadcrumb.component.ts index dd16a2f17..c13ffca06 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/breadcrumb/breadcrumb.component.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/breadcrumb/breadcrumb.component.ts @@ -3,10 +3,10 @@ import { Router } from '@angular/router'; import { BreadcrumbItems } from './breadcrumbItems'; import { BreadcrumbItemModel } from './breadcrumbItem.model'; import { VideoHearingsService } from '../../services/video-hearings.service'; -import { first } from 'rxjs/operators'; import { Subject } from 'rxjs'; -import { FeatureFlags, LaunchDarklyService } from 'src/app/services/launch-darkly.service'; +import { LaunchDarklyService } from 'src/app/services/launch-darkly.service'; import { PageUrls } from 'src/app/shared/page-url.constants'; + @Component({ selector: 'app-breadcrumb', templateUrl: './breadcrumb.component.html', @@ -18,27 +18,14 @@ export class BreadcrumbComponent implements OnInit, OnDestroy { currentItem: BreadcrumbItemModel; @Input() canNavigate: boolean; - addJudiciaryMemberFlag = false; destroyed$ = new Subject(); constructor(private router: Router, private videoHearingsService: VideoHearingsService, private featureService: LaunchDarklyService) {} ngOnInit() { this.currentRouter = this.router.url; - this.featureService - .getFlag(FeatureFlags.useV2Api) - .pipe(first()) - .subscribe(result => { - this.addJudiciaryMemberFlag = result; - let tempBreadcrumbModel: BreadcrumbItemModel[]; - if (this.addJudiciaryMemberFlag) { - tempBreadcrumbModel = BreadcrumbItems.filter(x => x.Url !== PageUrls.AssignJudge); - } else { - tempBreadcrumbModel = BreadcrumbItems.filter(x => x.Url !== PageUrls.AddJudicialOfficeHolders); - } - this.breadcrumbItems = tempBreadcrumbModel; - this.initBreadcrumb(); - }); + this.breadcrumbItems = BreadcrumbItems.filter(x => x.Url !== PageUrls.AssignJudge); + this.initBreadcrumb(); } ngOnDestroy(): void { @@ -73,7 +60,7 @@ export class BreadcrumbComponent implements OnInit, OnDestroy { if (item.Name !== 'Judge') { return false; } else { - return this.addJudiciaryMemberFlag ? !item.LastMinuteAmendable : item.LastMinuteAmendable; + return !item.LastMinuteAmendable; } }; this.currentItem = this.breadcrumbItems.find(s => s.Url === this.currentRouter); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.html b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.html index 53abba1bc..bca9dbb3e 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.html +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.html @@ -116,12 +116,7 @@

Search bookings

{{ title }}

-
diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.spec.ts index 3b336f310..98f96ccbe 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.spec.ts @@ -590,8 +590,6 @@ describe('BookingsListComponent', () => { videoHearingServiceSpy.getHearingTypes.and.returnValue(of(new Array())); configServiceSpy.getConfig.and.returnValue({}); - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.adminSearch).and.returnValue(of(true)); - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.vhoWorkAllocation).and.returnValue(of(true)); launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.useV2Api).and.returnValue(of(false)); referenceDataServiceSpy.getCourts.and.returnValue(of(new Array())); @@ -664,117 +662,6 @@ describe('BookingsListComponent', () => { expect(component.loaded).toBeTruthy(); }); - it('should onSearch (admin_search flag off)', () => { - bookingsListServiceSpy.getBookingsList.calls.reset(); - setFormValue(); - component.enableSearchFeature = false; - component.onSearch(); - expect(bookingPersistService.caseNumber).toMatch('CASE_NUMBER'); - expect(bookingPersistService.startDate).toEqual(moment().startOf('day').add(1, 'days').toDate()); - expect(bookingPersistService.endDate).toEqual(moment().startOf('day').add(2, 'days').toDate()); - expect(component.bookings.length).toBeGreaterThan(0); - expect(bookingsListServiceSpy.getBookingsList).toHaveBeenCalledWith(undefined, component.limit); - }); - - it('should onSearch (admin_search flag on)', () => { - bookingsListServiceSpy.getBookingsList.calls.reset(); - setFormValue(); - component.enableSearchFeature = true; - component.onSearch(); - expect(bookingPersistService.caseNumber).toMatch('CASE_NUMBER'); - expect(bookingPersistService.participantLastName).toMatch('PARTICIPANT_LAST_NAME'); - expect(bookingPersistService.startDate).toEqual(moment().startOf('day').add(1, 'days').toDate()); - expect(bookingPersistService.endDate).toEqual(moment().startOf('day').add(2, 'days').toDate()); - expect(component.bookings.length).toBeGreaterThan(0); - expect(bookingsListServiceSpy.getBookingsList).toHaveBeenCalledWith( - undefined, - component.limit, - bookingPersistService.caseNumber, - bookingPersistService.selectedVenueIds, - bookingPersistService.selectedCaseTypes, - bookingPersistService.selectedUsers, - moment(bookingPersistService.startDate).startOf('day').toDate(), - moment(bookingPersistService.endDate).endOf('day').toDate(), - bookingPersistService.participantLastName, - bookingPersistService.noJugdeInHearings, - bookingPersistService.noAllocatedHearings - ); - }); - - it('should onSearch (admin_search flag on) with populated endDate and empty startDate', () => { - bookingsListServiceSpy.getBookingsList.calls.reset(); - setFormValue(); - component.enableSearchFeature = true; - component.searchForm.controls['startDate'].setValue(null); - component.onSearch(); - expect(bookingPersistService.caseNumber).toMatch('CASE_NUMBER'); - expect(bookingPersistService.participantLastName).toMatch('PARTICIPANT_LAST_NAME'); - expect(bookingPersistService.startDate).toBeNull(); - expect(bookingPersistService.endDate).toEqual(moment().startOf('day').add(2, 'days').toDate()); - expect(component.bookings.length).toBeGreaterThan(0); - expect(bookingsListServiceSpy.getBookingsList).toHaveBeenCalledWith( - undefined, - component.limit, - bookingPersistService.caseNumber, - bookingPersistService.selectedVenueIds, - bookingPersistService.selectedCaseTypes, - bookingPersistService.selectedUsers, - moment(bookingPersistService.endDate).startOf('day').toDate(), - moment(bookingPersistService.endDate).endOf('day').toDate(), - bookingPersistService.participantLastName, - bookingPersistService.noJugdeInHearings, - bookingPersistService.noAllocatedHearings - ); - }); - - it('should onSearch (admin_search flag on) with populated startDate and empty endDate', () => { - bookingsListServiceSpy.getBookingsList.calls.reset(); - setFormValue(); - component.enableSearchFeature = true; - component.searchForm.controls['endDate'].setValue(null); - component.onSearch(); - expect(bookingPersistService.caseNumber).toMatch('CASE_NUMBER'); - expect(bookingPersistService.participantLastName).toMatch('PARTICIPANT_LAST_NAME'); - expect(bookingPersistService.startDate).toEqual(moment().startOf('day').add(1, 'days').toDate()); - expect(bookingPersistService.endDate).toBeNull(); - expect(component.bookings.length).toBeGreaterThan(0); - expect(bookingsListServiceSpy.getBookingsList).toHaveBeenCalledWith( - undefined, - component.limit, - bookingPersistService.caseNumber, - bookingPersistService.selectedVenueIds, - bookingPersistService.selectedCaseTypes, - bookingPersistService.selectedUsers, - moment(bookingPersistService.startDate).startOf('day').toDate(), - moment(bookingPersistService.startDate).endOf('day').toDate(), - bookingPersistService.participantLastName, - bookingPersistService.noJugdeInHearings, - bookingPersistService.noAllocatedHearings - ); - }); - - it('should onSearch (admin_search flag on) with no judge option selected', () => { - bookingsListServiceSpy.getBookingsList.calls.reset(); - setFormValue(true); - component.enableSearchFeature = true; - component.searchForm.controls['endDate'].setValue(null); - component.onSearch(); - expect(bookingPersistService.noJugdeInHearings).toBeTruthy(); - expect(bookingsListServiceSpy.getBookingsList).toHaveBeenCalledWith( - undefined, - component.limit, - bookingPersistService.caseNumber, - bookingPersistService.selectedVenueIds, - bookingPersistService.selectedCaseTypes, - bookingPersistService.selectedUsers, - moment(bookingPersistService.startDate).startOf('day').toDate(), - moment(bookingPersistService.startDate).endOf('day').toDate(), - bookingPersistService.participantLastName, - bookingPersistService.noJugdeInHearings, - bookingPersistService.noAllocatedHearings - ); - }); - describe('noJudgeInHearing', () => { it('no judge option is ON', () => { const optionSelected = true; @@ -795,7 +682,6 @@ describe('BookingsListComponent', () => { let startDateElement: HTMLInputElement; beforeEach(() => { - component.enableSearchFeature = true; component.openSearchPanel(); fixture.detectChanges(); startDateControl = component.searchForm.controls['startDate']; @@ -855,7 +741,6 @@ describe('BookingsListComponent', () => { let endDateElement: HTMLInputElement; beforeEach(() => { - component.enableSearchFeature = true; component.openSearchPanel(); fixture.detectChanges(); startDateControl = component.searchForm.controls['startDate']; @@ -909,18 +794,6 @@ describe('BookingsListComponent', () => { }); }); - it('should onClear (if workAllocation feature on)', () => { - spyOn(component, 'workAllocationEnabled').and.returnValue(true); - const csoMenu = onClearTest(); - expect(csoMenu).toHaveBeenCalledTimes(1); - }); - - it('should onClear (if workAllocation feature off)', () => { - spyOn(component, 'workAllocationEnabled').and.returnValue(false); - const csoMenu = onClearTest(); - expect(csoMenu).toHaveBeenCalledTimes(0); - }); - function onClearTest() { const formBuilder = new FormBuilder(); const bookingPersistServiceSpy = jasmine.createSpyObj('BookingPersistService', [ @@ -973,7 +846,6 @@ describe('BookingsListComponent', () => { component.venueMenu = new VenuesMenuComponent(bookingPersistServiceSpy, referenceDataServiceSpy, formBuilder, loggerSpy); setFormValue(); - component.enableSearchFeature = true; component.onSearch(); expect(component.title).toEqual('Search results'); component.onClear(); @@ -983,7 +855,6 @@ describe('BookingsListComponent', () => { it('should disable search button if all fields are empty', () => { component.openSearchPanel(); clearSearch(); - component.enableSearchFeature = true; fixture.detectChanges(); const searchButton = document.getElementById('searchButton') as HTMLButtonElement; expect(searchButton.disabled).toBe(false); @@ -993,7 +864,6 @@ describe('BookingsListComponent', () => { component.openSearchPanel(); clearSearch(); component.searchForm.controls['caseNumber'].setValue('CASE_NUMBER'); - component.enableSearchFeature = true; fixture.detectChanges(); const searchButton = document.getElementById('searchButton') as HTMLButtonElement; expect(searchButton.disabled).toBe(false); @@ -1003,7 +873,6 @@ describe('BookingsListComponent', () => { component.openSearchPanel(); clearSearch(); component.searchForm.controls['participantLastName'].setValue('PARTICIPANT_LAST_NAME'); - component.enableSearchFeature = true; fixture.detectChanges(); const searchButton = document.getElementById('searchButton') as HTMLButtonElement; expect(searchButton.disabled).toBe(false); @@ -1013,7 +882,6 @@ describe('BookingsListComponent', () => { component.openSearchPanel(); clearSearch(); component.searchForm.controls['startDate'].setValue(new Date(2022, 3, 25)); - component.enableSearchFeature = true; fixture.detectChanges(); const searchButton = document.getElementById('searchButton') as HTMLButtonElement; expect(searchButton.disabled).toBe(false); @@ -1023,7 +891,6 @@ describe('BookingsListComponent', () => { component.openSearchPanel(); clearSearch(); component.searchForm.controls['endDate'].setValue(new Date(2022, 3, 25)); - component.enableSearchFeature = true; fixture.detectChanges(); const searchButton = document.getElementById('searchButton') as HTMLButtonElement; expect(searchButton.disabled).toBe(false); @@ -1031,7 +898,6 @@ describe('BookingsListComponent', () => { it('should close search panel when close search button clicked', () => { component.openSearchPanel(); - component.enableSearchFeature = true; fixture.detectChanges(); let searchPanel = document.getElementById('searchPanel') as HTMLDivElement; expect(searchPanel).not.toBeNull(); @@ -1055,38 +921,6 @@ describe('BookingsListComponent', () => { expect(component.showSearch).toBe(false); }); - it('should not load venues when search feature is disabled', fakeAsync(() => { - referenceDataServiceSpy.getCourts.calls.reset(); - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.adminSearch).and.returnValue(of(false)); - - component.subscribeToFeatureFlags(); - tick(); - - expect(component.enableSearchFeature).toBeFalsy(); - })); - - it('should load venues when search feature is enabled', () => { - referenceDataServiceSpy.getCourts.calls.reset(); - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.adminSearch).and.returnValue(of(true)); - - fixture.detectChanges(); - expect(component.enableSearchFeature).toBeTruthy(); - }); - - it('should hide the search panel on initial load when search feature enabled', () => { - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.adminSearch).and.returnValue(of(true)); - component.ngOnInit(); - fixture.detectChanges(); - expect(component.showSearch).toBe(false); - }); - - it('should hide the search panel on initial load when search feature disabled', () => { - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.adminSearch).and.returnValue(of(false)); - component.ngOnInit(); - fixture.detectChanges(); - expect(component.showSearch).toBe(false); - }); - it('should add bookings list records on the next scroll and delete duplicated hearings', waitForAsync(() => { component.bookings = new ArrayBookingslistModelTestData().getTestData(); component.ngOnInit(); @@ -1279,21 +1113,5 @@ describe('BookingsListComponent', () => { component.onChangeNoAllocated(); expect(bookingPersistService.selectedUsers.length).toEqual(count); }); - - it('should not show allocated to label if work allocation feature flag is off', async () => { - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.vhoWorkAllocation).and.returnValue(of(false)); - await component.ngOnInit(); - fixture.detectChanges(); - const divToHide = fixture.debugElement.query(By.css('#allocated-to-' + bookingData.BookingsDetails[0].HearingId)); - expect(divToHide).toBeFalsy(); - }); - - it('should show allocated label to if work allocation feature flag is on', async () => { - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.vhoWorkAllocation).and.returnValue(of(true)); - await component.ngOnInit(); - fixture.detectChanges(); - const divToHide = fixture.debugElement.query(By.css('#allocated-to-' + bookingData.BookingsDetails[0].HearingId)); - expect(divToHide).toBeTruthy(); - }); }); }); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.ts index 4888861c0..02054d981 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.ts @@ -40,14 +40,12 @@ export class BookingsListComponent implements OnInit, OnDestroy { bookingResponse: BookingsModel; $subcription: Subscription; searchForm: FormGroup; - enableSearchFeature: boolean; title = this.initialTitle; selectedVenueIds: []; selectedCaseTypes: string[]; selectedUserIds: []; showSearch = false; today = new Date(); - vhoWorkAllocationFeature = false; isV2 = false; destroyed$ = new Subject(); @@ -181,27 +179,19 @@ export class BookingsListComponent implements OnInit, OnDestroy { if (endDate && !startDate) { startDate = moment(endDate).startOf('day').toDate(); } - let bookingsList$: Observable; - - if (this.enableSearchFeature) { - // new feature - bookingsList$ = this.bookingsListService.getBookingsList( - this.cursor, - this.limit, - caseNumber, - venueIds, - caseTypes, - users, - startDate, - endDate, - lastName, - noJudge, - noAllocated - ); - } else { - // previous implementation - bookingsList$ = this.bookingsListService.getBookingsList(this.cursor, this.limit); - } + const bookingsList$: Observable = this.bookingsListService.getBookingsList( + this.cursor, + this.limit, + caseNumber, + venueIds, + caseTypes, + users, + startDate, + endDate, + lastName, + noJudge, + noAllocated + ); this.$subcription = bookingsList$.subscribe({ next: book => self.loadData(book), @@ -256,9 +246,7 @@ export class BookingsListComponent implements OnInit, OnDestroy { this.bookingPersistService.selectedCaseTypes = []; this.caseTypeMenu.clear(); this.bookingPersistService.selectedUsers = []; - if (this.workAllocationEnabled()) { - this.csoMenu.clear(); - } + this.csoMenu.clear(); this.bookingPersistService.startDate = null; this.bookingPersistService.endDate = null; this.bookingPersistService.participantLastName = ''; @@ -479,10 +467,6 @@ export class BookingsListComponent implements OnInit, OnDestroy { } } - workAllocationEnabled(): boolean { - return this.vhoWorkAllocationFeature; - } - selectedCaseTypesEmitter($event: string[]) { this.bookingPersistService.selectedCaseTypes = $event; } @@ -492,20 +476,6 @@ export class BookingsListComponent implements OnInit, OnDestroy { } subscribeToFeatureFlags() { - this.lanchDarklyService - .getFlag(FeatureFlags.adminSearch) - .pipe(takeUntil(this.destroyed$)) - .subscribe(flag => { - this.enableSearchFeature = flag; - }); - - this.lanchDarklyService - .getFlag(FeatureFlags.vhoWorkAllocation) - .pipe(takeUntil(this.destroyed$)) - .subscribe(flag => { - this.vhoWorkAllocationFeature = flag; - }); - this.lanchDarklyService .getFlag(FeatureFlags.useV2Api) .pipe(takeUntil(this.destroyed$)) diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/hearing-details/hearing-details.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/hearing-details/hearing-details.component.spec.ts index 9400ea538..482ea7495 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/hearing-details/hearing-details.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/hearing-details/hearing-details.component.spec.ts @@ -11,14 +11,9 @@ import { ClientSettingsResponse } from 'src/app/services/clients/api-client'; import { Logger } from '../../services/logger'; import { OtherInformationModel } from '../../common/model/other-information.model'; import { ConfigService } from 'src/app/services/config.service'; -import { of } from 'rxjs'; -import { FeatureFlags, LaunchDarklyService } from '../../services/launch-darkly.service'; import { SharedModule } from 'src/app/shared/shared.module'; -const launchDarklyServiceSpy = jasmine.createSpyObj('LaunchDarklyService', ['getFlag']); - describe('HearingDetailsComponent', () => { - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.vhoWorkAllocation).and.returnValue(of(true)); let component: HearingDetailsComponent; let fixture: ComponentFixture; let debugElement: DebugElement; @@ -59,11 +54,7 @@ describe('HearingDetailsComponent', () => { TestBed.configureTestingModule({ declarations: [HearingDetailsComponent, LongDatetimePipe], imports: [RouterTestingModule, SharedModule], - providers: [ - Logger, - { provide: ConfigService, useValue: configServiceSpy }, - { provide: LaunchDarklyService, useValue: launchDarklyServiceSpy } - ] + providers: [Logger, { provide: ConfigService, useValue: configServiceSpy }] }).compileComponents(); })); @@ -150,23 +141,6 @@ describe('HearingDetailsComponent', () => { const result = component.getDefenceAdvocateByContactEmail('madeup@doesnotexist.com'); expect(result).toBe(''); }); - describe('feature flag turn on and off ', () => { - it('should not show allocated to label if work allocation feature flag is off', async () => { - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.vhoWorkAllocation).and.returnValue(of(false)); - await component.ngOnInit(); - fixture.detectChanges(); - const divToHide = fixture.debugElement.query(By.css('#hearing-allocated-to')); - expect(divToHide).toBeFalsy(); - }); - - it('should show allocated to label if work allocation feature flag is on', async () => { - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.vhoWorkAllocation).and.returnValue(of(true)); - await component.ngOnInit(); - fixture.detectChanges(); - const divToHide = fixture.debugElement.query(By.css('#hearing-allocated-to')); - expect(divToHide).toBeTruthy(); - }); - }); }); describe('HearingDetailsComponent join by phone', () => { const clientSettings = new ClientSettingsResponse({ @@ -204,7 +178,7 @@ describe('HearingDetailsComponent join by phone', () => { '1234567' ); it('should display option to join by phone if config has not the set date', () => { - const component = new HearingDetailsComponent(activatedRoute, loggerSpy, configServiceSpy, launchDarklyServiceSpy); + const component = new HearingDetailsComponent(activatedRoute, loggerSpy, configServiceSpy); component.hearing = hearing; const result = component.isJoinByPhone(); expect(result).toBe(true); @@ -212,7 +186,7 @@ describe('HearingDetailsComponent join by phone', () => { it('should not display option to join by phone if booking has not confirmation date', () => { clientSettings.join_by_phone_from_date = '2020-10-22'; hearing.ConfirmedDate = null; - const component = new HearingDetailsComponent(activatedRoute, loggerSpy, configServiceSpy, launchDarklyServiceSpy); + const component = new HearingDetailsComponent(activatedRoute, loggerSpy, configServiceSpy); component.hearing = hearing; const result = component.isJoinByPhone(); expect(result).toBe(false); @@ -220,7 +194,7 @@ describe('HearingDetailsComponent join by phone', () => { it('should not display option to join by phone if booking confirmation date less than config date', () => { clientSettings.join_by_phone_from_date = '2020-10-22'; hearing.ConfirmedDate = new Date('2020-10-21'); - const component = new HearingDetailsComponent(activatedRoute, loggerSpy, configServiceSpy, launchDarklyServiceSpy); + const component = new HearingDetailsComponent(activatedRoute, loggerSpy, configServiceSpy); component.hearing = hearing; const result = component.isJoinByPhone(); expect(result).toBe(false); @@ -228,7 +202,7 @@ describe('HearingDetailsComponent join by phone', () => { it('should display option to join by phone if booking confirmation date greater than config date', () => { clientSettings.join_by_phone_from_date = '2020-10-22'; hearing.ConfirmedDate = new Date('2020-10-23'); - const component = new HearingDetailsComponent(activatedRoute, loggerSpy, configServiceSpy, launchDarklyServiceSpy); + const component = new HearingDetailsComponent(activatedRoute, loggerSpy, configServiceSpy); component.hearing = hearing; const result = component.isJoinByPhone(); expect(result).toBe(true); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/hearing-details/hearing-details.component.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/hearing-details/hearing-details.component.ts index 0744642ca..3f03e89a7 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/hearing-details/hearing-details.component.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/hearing-details/hearing-details.component.ts @@ -6,7 +6,6 @@ import { Logger } from '../../services/logger'; import { OtherInformationModel } from '../../common/model/other-information.model'; import { ConfigService } from 'src/app/services/config.service'; import { Subject, Subscription, takeUntil } from 'rxjs'; -import { FeatureFlags, LaunchDarklyService } from '../../services/launch-darkly.service'; @Component({ selector: 'app-hearing-details', @@ -24,28 +23,15 @@ export class HearingDetailsComponent implements OnInit, OnDestroy { private readonly loggerPrefix = '[HearingDetails] -'; phoneConferenceDetails = ''; - vhoWorkAllocationFeature = false; $subcription: Subscription; destroyed$ = new Subject(); enableSearchFeature: boolean; ejudFeatureFlag: boolean; - constructor( - private route: ActivatedRoute, - private logger: Logger, - private configService: ConfigService, - private lanchDarklyService: LaunchDarklyService - ) {} + constructor(private route: ActivatedRoute, private logger: Logger, private configService: ConfigService) {} - ngOnInit() { - this.lanchDarklyService - .getFlag(FeatureFlags.vhoWorkAllocation) - .pipe(takeUntil(this.destroyed$)) - .subscribe(flag => { - this.vhoWorkAllocationFeature = flag; - }); - } + ngOnInit() {} ngOnDestroy(): void { this.destroyed$.next(); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/dashboard/dashboard.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/dashboard/dashboard.component.spec.ts index 2d16f3f55..b839cb2ba 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/dashboard/dashboard.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/dashboard/dashboard.component.spec.ts @@ -16,7 +16,6 @@ describe('DashboardComponent', () => { const loggerSpy = jasmine.createSpyObj('Logger', ['error', 'debug', 'warn']); beforeEach(waitForAsync(() => { - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.vhoWorkAllocation).and.returnValue(of(true)); launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.audioSearch).and.returnValue(of(false)); launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.dom1Integration).and.returnValue(of(false)); @@ -132,36 +131,6 @@ describe('DashboardComponent', () => { expect(component.showWorkAllocation).toBeFalsy(); }); - it('should not show work allocation tile if feature is switched off', async () => { - userIdentitySpy.getUserInformation.and.returnValue( - of( - new UserProfileResponse({ - is_case_administrator: true, - is_vh_officer_administrator_role: true - }) - ) - ); - - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.vhoWorkAllocation).and.returnValue(of(false)); - - await component.ngOnInit(); - expect(component.showWorkAllocation).toBeFalsy(); - }); - - it('should show work allocation tile if feature is switched on and user is Team Leader', async () => { - userIdentitySpy.getUserInformation.and.returnValue( - of( - new UserProfileResponse({ - is_vh_team_leader: true - }) - ) - ); - - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.vhoWorkAllocation).and.returnValue(of(true)); - await component.ngOnInit(); - expect(component.showWorkAllocation).toBeTruthy(); - }); - it('should unsubscribe from launch darkly flag changes', () => { const unsubscribeSpy = spyOn(component.destroyed$, 'next'); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/dashboard/dashboard.component.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/dashboard/dashboard.component.ts index dc94c9d44..b25e5ecd4 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/dashboard/dashboard.component.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/dashboard/dashboard.component.ts @@ -24,7 +24,6 @@ export class DashboardComponent implements OnInit, OnDestroy { showCheckList = false; showBooking = false; showWorkAllocation = false; - vhoWorkAllocationFeature = false; dom1Feature = false; audioSearchFeature: boolean; @@ -34,32 +33,25 @@ export class DashboardComponent implements OnInit, OnDestroy { destroyed$ = new Subject(); ngOnInit() { - const workAllocationFlag$ = this.launchDarklyService - .getFlag(FeatureFlags.vhoWorkAllocation) - .pipe(takeUntil(this.destroyed$)); const audioSearchFlag$ = this.launchDarklyService.getFlag(FeatureFlags.audioSearch).pipe(takeUntil(this.destroyed$)); const dom1FeatureFlag$ = this.launchDarklyService.getFlag(FeatureFlags.dom1Integration).pipe(takeUntil(this.destroyed$)); - combineLatest([workAllocationFlag$, audioSearchFlag$, dom1FeatureFlag$]).subscribe( - ([workAllocationFlag, audioSearchFlag, dom1FeatureFlag]) => { - this.vhoWorkAllocationFeature = workAllocationFlag; - this.audioSearchFeature = audioSearchFlag; - console.log('################### ' + audioSearchFlag); - this.dom1Feature = dom1FeatureFlag; - lastValueFrom(this.userIdentityService.getUserInformation()).then(profile => { - this.showCheckList = profile.is_vh_officer_administrator_role; - this.showWorkAllocation = profile.is_vh_team_leader && this.vhoWorkAllocationFeature; - this.showAudioFileLink = this.showCheckList && !this.audioSearchFeature; - this.showBooking = profile.is_case_administrator || profile.is_vh_officer_administrator_role; - this.showManageTeam = profile.is_vh_team_leader && this.dom1Feature; - this.logger.debug(`${this.loggerPrefix} Landed on dashboard`, { - showCheckList: this.showCheckList, - showBooking: this.showBooking, - showWorkAllocation: this.showWorkAllocation - }); + combineLatest([audioSearchFlag$, dom1FeatureFlag$]).subscribe(([audioSearchFlag, dom1FeatureFlag]) => { + this.audioSearchFeature = audioSearchFlag; + this.dom1Feature = dom1FeatureFlag; + lastValueFrom(this.userIdentityService.getUserInformation()).then(profile => { + this.showCheckList = profile.is_vh_officer_administrator_role; + this.showWorkAllocation = profile.is_vh_team_leader; + this.showAudioFileLink = this.showCheckList && !this.audioSearchFeature; + this.showBooking = profile.is_case_administrator || profile.is_vh_officer_administrator_role; + this.showManageTeam = profile.is_vh_team_leader && this.dom1Feature; + this.logger.debug(`${this.loggerPrefix} Landed on dashboard`, { + showCheckList: this.showCheckList, + showBooking: this.showBooking, + showWorkAllocation: this.showWorkAllocation }); - } - ); + }); + }); } ngOnDestroy() { diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/work-allocation-feature.guard.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/work-allocation-feature.guard.spec.ts deleted file mode 100644 index e30422e43..000000000 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/work-allocation-feature.guard.spec.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { TestBed } from '@angular/core/testing'; -import { Router } from '@angular/router'; -import { of } from 'rxjs'; -import { FeatureFlags, LaunchDarklyService } from '../../services/launch-darkly.service'; -import { WorkAllocationFeatureGuard } from './work-allocation-feature.guard'; - -describe('WorkAllocationFeatureGuard', () => { - let workAllocationFeatureGuard: WorkAllocationFeatureGuard; - - const launchDarklyServiceSpy = jasmine.createSpyObj('LaunchDarklyService', ['getFlag']); - - const routerSpy = jasmine.createSpyObj('Router', ['navigate']); - - beforeEach(() => { - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.vhoWorkAllocation).and.returnValue(of(true)); - - TestBed.configureTestingModule({ - providers: [ - WorkAllocationFeatureGuard, - { provide: Router, useValue: routerSpy }, - { provide: LaunchDarklyService, useValue: launchDarklyServiceSpy } - ] - }).compileComponents(); - workAllocationFeatureGuard = TestBed.inject(WorkAllocationFeatureGuard); - }); - - it('should return true if feature toggle is on', () => { - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.vhoWorkAllocation).and.returnValue(of(true)); - workAllocationFeatureGuard.canActivate(null, null).subscribe(result => { - expect(result).toBeTruthy(); - }); - }); - - it('should redirect to home page if feature toggle is off', () => { - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.vhoWorkAllocation).and.returnValue(of(false)); - workAllocationFeatureGuard.canActivate(null, null).subscribe(result => { - expect(result).toBeFalsy(); - expect(routerSpy.navigate).toHaveBeenCalledWith(['/']); - }); - }); -}); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/work-allocation-feature.guard.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/work-allocation-feature.guard.ts deleted file mode 100644 index bf90d4673..000000000 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/work-allocation-feature.guard.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Injectable } from '@angular/core'; -import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router'; -import { Observable } from 'rxjs'; -import { FeatureFlags, LaunchDarklyService } from '../../services/launch-darkly.service'; -import { map, take } from 'rxjs/operators'; - -@Injectable() -export class WorkAllocationFeatureGuard { - private readonly loggerPrefix = '[WorkAllocationFeatureGuard] -'; - - constructor(private launchDarklyService: LaunchDarklyService, private router: Router) {} - - canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { - return this.launchDarklyService.getFlag(FeatureFlags.vhoWorkAllocation).pipe( - take(1), - map(featureEnabled => { - if (featureEnabled) { - return true; - } - this.router.navigate(['/']); - return false; - }) - ); - } -} diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.ts index fef74de91..51b67d2c3 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.ts @@ -5,8 +5,6 @@ import { Observable, Subject } from 'rxjs'; import { first, map } from 'rxjs/operators'; export const FeatureFlags = { - adminSearch: 'admin_search', - vhoWorkAllocation: 'vho-work-allocation', dom1Integration: 'dom1', hrsIntegration: 'hrs-integration', referenceData: 'reference-data', diff --git a/AdminWebsite/AdminWebsite/Configuration/FeatureToggles.cs b/AdminWebsite/AdminWebsite/Configuration/FeatureToggles.cs index 5346a7102..a25f7548e 100644 --- a/AdminWebsite/AdminWebsite/Configuration/FeatureToggles.cs +++ b/AdminWebsite/AdminWebsite/Configuration/FeatureToggles.cs @@ -8,13 +8,10 @@ namespace AdminWebsite.Configuration { public interface IFeatureToggles { - public bool BookAndConfirmToggle(); public bool Dom1Enabled(); public bool ReferenceDataToggle(); public bool UseV2Api(); public bool HrsEnabled(); - public bool AudioSearchEnabled(); - public bool UsePostMay2023Template(); } public class FeatureToggles : IFeatureToggles @@ -22,13 +19,10 @@ public class FeatureToggles : IFeatureToggles private readonly ILdClient _ldClient; private readonly Context _context; private const string LdUser = "vh-admin-web"; - private const string BookAndConfirmToggleKey = "Book_and_Confirm"; private const string Dom1EnabledToggleKey = "dom1"; private const string ReferenceDataToggleKey = "reference-data"; private const string UseV2ApiToggleKey = "use-bookings-api-v2"; private const string HrsFeatureToggleKey = "hrs-integration"; - private const string AudioSearchToggleKey = "hide-audio-search-tile"; - private const string UsePostMay2023TemplateKey = "notify-post-may-2023-templates"; public FeatureToggles(string sdkKey, string environmentName) @@ -39,11 +33,6 @@ public FeatureToggles(string sdkKey, string environmentName) _ldClient = new LdClient(config); } - public bool BookAndConfirmToggle() - { - return GetBoolValueWithKey(BookAndConfirmToggleKey); - } - public bool Dom1Enabled() { return GetBoolValueWithKey(Dom1EnabledToggleKey); @@ -59,21 +48,11 @@ public bool HrsEnabled() return GetBoolValueWithKey(HrsFeatureToggleKey); } - public bool AudioSearchEnabled() - { - return GetBoolValueWithKey(AudioSearchToggleKey); - } - public bool UseV2Api() { return GetBoolValueWithKey(UseV2ApiToggleKey); } - public bool UsePostMay2023Template() - { - return GetBoolValueWithKey(UsePostMay2023TemplateKey); - } - private bool GetBoolValueWithKey(string key) { if (!_ldClient.Initialized) diff --git a/AdminWebsite/AdminWebsite/Controllers/HearingsController.cs b/AdminWebsite/AdminWebsite/Controllers/HearingsController.cs index 663d5d4fa..88a13fc5f 100644 --- a/AdminWebsite/AdminWebsite/Controllers/HearingsController.cs +++ b/AdminWebsite/AdminWebsite/Controllers/HearingsController.cs @@ -1048,8 +1048,7 @@ public async Task GetHearingConferenceStatus(Guid hearingId) var participantsNeedVHAccounts = ParticipantsNeedVHAccounts(response.Participants); var accountsStillNeedCreating = participantsNeedVHAccounts.Any(x => x.ContactEmail == x.Username); var isMultiDay = response.GroupId != null; - var isNotifyFlagOn = _featureToggles.UsePostMay2023Template(); - if (isMultiDay && isNotifyFlagOn) + if (isMultiDay) { // Users are created as part of the clone process, so don't wait for them here accountsStillNeedCreating = false; From 26aa1bfdbfbceddabeeca8b7bde33e8e213ef786 Mon Sep 17 00:00:00 2001 From: marcogagliardi Date: Mon, 10 Jun 2024 08:51:07 +0100 Subject: [PATCH 02/25] removed notify-post-may-2023-templates --- .../HearingsController/BookNewHearingTests.cs | 46 ------ .../CancelMultiDayHearingTests.cs | 99 ++----------- .../HearingsController/EditHearingTests.cs | 62 +++------ .../EditMultiDayHearingTests.cs | 32 ++--- .../HearingsController/GetHearingTests.cs | 131 +----------------- .../GetStatusHearingTests.cs | 3 +- .../ReferenceDataControllerTests.cs | 15 +- .../Configuration/FeatureToggles.cs | 12 +- .../Controllers/HearingsController.cs | 100 +++---------- .../Controllers/ReferenceDataController.cs | 13 +- .../AdminWebsite/Services/HearingsService.cs | 2 +- 11 files changed, 81 insertions(+), 434 deletions(-) diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/BookNewHearingTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/BookNewHearingTests.cs index 8950585b6..240f25c9c 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/BookNewHearingTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/BookNewHearingTests.cs @@ -234,52 +234,6 @@ public async Task Should_book_hearing_for_multi_day() _mocker.Mock().Verify(x => x.BookNewHearingAsync(It.IsAny()), Times.Once); } - - [Test] - public async Task Should_book_hearing_with_use_v2_api_flag_on() - { - // Arrange - _mocker.Mock().Setup(x => x.UseV2Api()).Returns(true); - var bookingDetails = InitHearingForV2Test(); - - var bookingRequest = new BookHearingRequest - { - BookingDetails = bookingDetails - }; - - var hearingDetailsResponse = HearingResponseV2Builder.Build() - .WithEndPoints(2) - .WithParticipant("Representative", "username1@hmcts.net") - .WithParticipant("Individual", "fname2.lname2@hmcts.net") - .WithParticipant("Individual", "fname3.lname3@hmcts.net") - .WithParticipant("Judicial Office Holder", "fname4.lname4@hmcts.net") - .WithParticipant("Judge", "judge.fudge@hmcts.net"); - - _mocker.Mock().Setup(x => x.BookNewHearingWithCodeAsync(It.IsAny())) - .ReturnsAsync(hearingDetailsResponse); - - - _mocker.Mock().Setup(x => x.GetUserIdentityName()).Returns(_expectedUserIdentityName); - - // Act - var result = await _controller.Post(bookingRequest); - - // Assert - result.Result.Should().BeOfType(); - var createdObjectResult = (CreatedResult) result.Result; - createdObjectResult.StatusCode.Should().Be(201); - createdObjectResult.Value.Should().BeEquivalentTo(hearingDetailsResponse, options => options.ExcludingMissingMembers()); - - bookingDetails.Participants.Exists(x => string.IsNullOrWhiteSpace(x.Username)).Should().BeFalse(); - - bookingDetails.CreatedBy.Should().Be(_expectedUserIdentityName); - - _mocker.Mock().Verify(x - => x.AssignEndpointDefenceAdvocates(It.IsAny>(), - It.Is>(x => x.SequenceEqual(bookingDetails.Participants.AsReadOnly()))), Times.Once); - - _mocker.Mock().Verify(x => x.BookNewHearingWithCodeAsync(It.IsAny()), Times.Once); - } [Test] public async Task Should_catch_bookings_api_exceptions_and_return_bad_request_if_that_was_the_status_code() diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/CancelMultiDayHearingTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/CancelMultiDayHearingTests.cs index 8189e072e..094e5777c 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/CancelMultiDayHearingTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/CancelMultiDayHearingTests.cs @@ -24,69 +24,10 @@ protected override void Setup() UserIdentity.Setup(x => x.GetUserIdentityName()).Returns(UpdatedBy); } - [TestCase(false)] - [TestCase(true)] - public async Task should_cancel_multi_day_hearing_for_v1(bool updateFutureDays) - { - // Arrange - var hearingId = Guid.NewGuid(); - var groupId = Guid.NewGuid(); - var hearingDates = new List - { - DateTime.Today.AddDays(1).AddHours(10), - DateTime.UtcNow.AddDays(2).AddHours(10), - DateTime.UtcNow.AddDays(3).AddHours(10), - DateTime.UtcNow.AddDays(4).AddHours(10), - DateTime.UtcNow.AddDays(5).AddHours(10), - }; - var existingHearingsInMultiDayGroup = CreateListOfV1HearingsInMultiDayGroup(groupId, hearingId, scheduledDates: hearingDates); - existingHearingsInMultiDayGroup[3].Status = BookingStatus.Cancelled; - existingHearingsInMultiDayGroup[4].Status = BookingStatus.Failed; - BookingsApiClient.Setup(x => x.GetHearingsByGroupIdAsync(groupId)).ReturnsAsync(existingHearingsInMultiDayGroup); - var hearing = existingHearingsInMultiDayGroup.First(x => x.Id == hearingId); - BookingsApiClient.Setup(x => x.GetHearingDetailsByIdAsync(hearingId)).ReturnsAsync(hearing); - - var request = CreateRequest(); - request.UpdateFutureDays = updateFutureDays; - - FeatureToggle.Setup(e => e.UseV2Api()).Returns(false); - - // Act - var response = await Controller.CancelMultiDayHearing(hearing.Id, request); - - // Assert - var result = (OkObjectResult)response; - result.StatusCode.Should().Be(StatusCodes.Status200OK); - result.Value.Should().NotBeNull().And.BeAssignableTo().Subject.Success.Should().BeTrue(); - - var expectedUpdatedHearings = new List(); - if (updateFutureDays) - { - expectedUpdatedHearings.AddRange(existingHearingsInMultiDayGroup); - } - else - { - expectedUpdatedHearings.Add(hearing); - } - - expectedUpdatedHearings = expectedUpdatedHearings - .Where(h => - h.Status != BookingStatus.Cancelled && - h.Status != BookingStatus.Failed) - .ToList(); - - BookingsApiClient.Verify(x => x.CancelHearingsInGroupAsync( - groupId, - It.Is(r => - r.UpdatedBy == UpdatedBy && - r.CancelReason == request.CancelReason && - r.HearingIds.SequenceEqual(expectedUpdatedHearings.Select(h => h.Id)))), - Times.Once); - } [TestCase(false)] [TestCase(true)] - public async Task should_cancel_multi_day_hearing_for_v2(bool updateFutureDays) + public async Task should_cancel_multi_day_hearing(bool updateFutureDays) { // Arrange var hearingId = Guid.NewGuid(); @@ -109,9 +50,7 @@ public async Task should_cancel_multi_day_hearing_for_v2(bool updateFutureDays) var request = CreateRequest(); request.UpdateFutureDays = updateFutureDays; - - FeatureToggle.Setup(e => e.UseV2Api()).Returns(true); - + // Act var response = await Controller.CancelMultiDayHearing(hearing.Id, request); @@ -145,9 +84,8 @@ public async Task should_cancel_multi_day_hearing_for_v2(bool updateFutureDays) Times.Once); } - [TestCase(false)] - [TestCase(true)] - public async Task Should_forward_not_found_from_bookings_api(bool useV2) + [Test] + public async Task Should_forward_not_found_from_bookings_api() { // Arrange var hearingId = Guid.NewGuid(); @@ -159,17 +97,8 @@ public async Task Should_forward_not_found_from_bookings_api(bool useV2) null, errorMessage, null); - if (useV2) - { - BookingsApiClient.Setup(x => x.GetHearingDetailsByIdV2Async(hearingId)) + BookingsApiClient.Setup(x => x.GetHearingDetailsByIdV2Async(hearingId)) .ThrowsAsync(apiException); - } - else - { - BookingsApiClient.Setup(x => x.GetHearingDetailsByIdAsync(hearingId)) - .ThrowsAsync(apiException); - } - FeatureToggle.Setup(e => e.UseV2Api()).Returns(useV2); // Act var result = await Controller.CancelMultiDayHearing(hearingId, request); @@ -179,9 +108,8 @@ public async Task Should_forward_not_found_from_bookings_api(bool useV2) notFoundResult.Value.Should().Be(errorMessage); } - [TestCase(false)] - [TestCase(true)] - public async Task Should_return_bad_request_when_hearing_is_not_multi_day(bool useV2) + [Test] + public async Task Should_return_bad_request_when_hearing_is_not_multi_day() { // Arrange var hearingId = Guid.NewGuid(); @@ -189,16 +117,9 @@ public async Task Should_return_bad_request_when_hearing_is_not_multi_day(bool u var existingHearingsInMultiDayGroup = CreateListOfV1HearingsInMultiDayGroup(groupId, hearingId); var hearing = existingHearingsInMultiDayGroup.First(x => x.Id == hearingId); hearing.GroupId = null; - if (useV2) - { - var mappedHearing = MapHearingDetailsForV2(hearing); - BookingsApiClient.Setup(x => x.GetHearingDetailsByIdV2Async(hearingId)).ReturnsAsync(mappedHearing); - } - else - { - BookingsApiClient.Setup(x => x.GetHearingDetailsByIdAsync(hearingId)).ReturnsAsync(hearing); - } - FeatureToggle.Setup(e => e.UseV2Api()).Returns(useV2); + + var mappedHearing = MapHearingDetailsForV2(hearing); + BookingsApiClient.Setup(x => x.GetHearingDetailsByIdV2Async(hearingId)).ReturnsAsync(mappedHearing); var request = CreateRequest(); diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditHearingTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditHearingTests.cs index b98fb816b..f0ceee950 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditHearingTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditHearingTests.cs @@ -517,7 +517,7 @@ public async Task Should_add_panel_members_for_a_hearing(string confirmedBy) } [Test] - public async Task Should_return_updated_hearing() + public async Task Should_return_updated_hearing1() { var updatedHearing = new HearingDetailsResponse { @@ -548,9 +548,8 @@ public async Task Should_return_updated_hearing() } [Test] - public async Task Should_return_updated_hearingV2() + public async Task Should_return_updated_hearing2() { - _featureToggle.Setup(e => e.UseV2Api()).Returns(true); var updatedHearing = _v2HearingDetailsResponse; _bookingsApiClient.SetupSequence(x => x.GetHearingDetailsByIdV2Async(It.IsAny())) .ReturnsAsync(updatedHearing) @@ -635,9 +634,8 @@ public async Task Should_return_updated_hearingV2() } [Test] - public async Task Should_return_updated_hearingV2_with_no_participants_provided() + public async Task Should_return_updated_hearingV2() { - _featureToggle.Setup(e => e.UseV2Api()).Returns(true); var updatedHearing = _v2HearingDetailsResponse; updatedHearing.Participants.Clear(); _bookingsApiClient.SetupSequence(x => x.GetHearingDetailsByIdV2Async(It.IsAny())) @@ -679,7 +677,6 @@ public async Task Should_return_updated_hearingV2_with_no_participants_provided( [Test] public async Task Should_return_updated_hearingV2_with_no_judiciary_participants_provided() { - _featureToggle.Setup(e => e.UseV2Api()).Returns(true); var updatedHearing = _v2HearingDetailsResponse; updatedHearing.Participants.Clear(); updatedHearing.JudiciaryParticipants.Clear(); @@ -714,7 +711,6 @@ public async Task Should_return_updated_hearingV2_with_no_judiciary_participants [Test] public async Task Should_return_updated_hearingV2_with_new_judge_different_to_old_judge() { - _featureToggle.Setup(e => e.UseV2Api()).Returns(true); var updatedHearing = _v2HearingDetailsResponse; updatedHearing.Participants.Clear(); _bookingsApiClient.SetupSequence(x => x.GetHearingDetailsByIdV2Async(It.IsAny())) @@ -761,7 +757,6 @@ public async Task Should_return_updated_hearingV2_with_new_judge_different_to_ol [Test] public async Task Should_return_updated_hearingV2_with_new_judge_and_no_old_judge() { - _featureToggle.Setup(e => e.UseV2Api()).Returns(true); var updatedHearing = _v2HearingDetailsResponse; updatedHearing.Participants.Clear(); updatedHearing.JudiciaryParticipants.Clear(); @@ -800,7 +795,6 @@ public async Task Should_return_updated_hearingV2_with_new_judge_and_no_old_judg [Test] public async Task Should_return_updated_hearingV2_with_old_judge_and_no_new_judge() { - _featureToggle.Setup(e => e.UseV2Api()).Returns(true); var updatedHearing = _v2HearingDetailsResponse; updatedHearing.Participants.Clear(); _bookingsApiClient.SetupSequence(x => x.GetHearingDetailsByIdV2Async(It.IsAny())) @@ -831,7 +825,6 @@ public async Task Should_return_updated_hearingV2_with_old_judge_and_no_new_judg [Test] public async Task Should_reassign_a_generic_judge_booked_with_v1_to_ejud_judge_on_v2() { - _featureToggle.Setup(e => e.UseV2Api()).Returns(true); var updatedHearing = _v2HearingDetailsResponse; updatedHearing.Participants.Add(new () { @@ -877,7 +870,6 @@ public async Task Should_reassign_a_generic_judge_booked_with_v1_to_ejud_judge_o [Test] public async Task Should_return_updated_hearingV2_with_participants_unchanged_and_hearing_close_to_start_time() { - _featureToggle.Setup(e => e.UseV2Api()).Returns(true); var updatedHearing = _v2HearingDetailsResponse; updatedHearing.Participants.Clear(); _bookingsApiClient.SetupSequence(x => x.GetHearingDetailsByIdV2Async(It.IsAny())) @@ -1087,48 +1079,30 @@ public async Task Should_update_endpoint_if_an_endpoint_is_updates_in_endpoint_l } - [TestCase(false)] - [TestCase(true)] - public async Task Should_update_endpoint_to_be_linked_to_new_defence_advocate_when_endpoint_is_not_currently_linked(bool useV2) + [Test] + public async Task Should_update_endpoint_to_be_linked_to_new_defence_advocate_when_endpoint_is_not_currently_linked() { // ie there is an endpoint currently not linked to a defence advocate // as part of the request we add a new participant and link them to this endpoint as a defence advocate - // Arrange - _featureToggle.Setup(x => x.UseV2Api()).Returns(useV2); - Guid hearingId; var request = _editEndpointOnHearingRequestWithJudge; var endpointInRequestToUpdate = request.Endpoints[0]; - if (useV2) - { - var hearing = _v2HearingDetailsResponse; - hearingId = hearing.Id; - var existingEndpointToUpdate = new EndpointResponseV2 - { - Id = endpointInRequestToUpdate.Id.Value, - DisplayName = "Endpoint A", - DefenceAdvocateId = null - }; - hearing.Endpoints.RemoveAll(e => e.Id != existingEndpointToUpdate.Id); - hearing.Endpoints.Add(existingEndpointToUpdate); - - _bookingsApiClient.Setup(x => x.GetHearingDetailsByIdV2Async(It.IsAny())) - .ReturnsAsync(hearing); - } - else + var hearing = _v2HearingDetailsResponse; + hearingId = hearing.Id; + var existingEndpointToUpdate = new EndpointResponseV2 { - var hearing = _existingHearingWithEndpointsOriginal; - hearingId = hearing.Id; - var existingEndpointToUpdate = hearing.Endpoints[0]; - existingEndpointToUpdate.DefenceAdvocateId = null; - hearing.Endpoints.RemoveAll(e => e.Id != existingEndpointToUpdate.Id); - - _bookingsApiClient.Setup(x => x.GetHearingDetailsByIdAsync(It.IsAny())) - .ReturnsAsync(hearing); - } - + Id = endpointInRequestToUpdate.Id.Value, + DisplayName = "Endpoint A", + DefenceAdvocateId = null + }; + hearing.Endpoints.RemoveAll(e => e.Id != existingEndpointToUpdate.Id); + hearing.Endpoints.Add(existingEndpointToUpdate); + + _bookingsApiClient.Setup(x => x.GetHearingDetailsByIdV2Async(It.IsAny())) + .ReturnsAsync(hearing); + var newParticipantDefenceAdvocate = new EditParticipantRequest { ContactEmail = "legalrep@email.com", diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditMultiDayHearingTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditMultiDayHearingTests.cs index 5c16dd0d8..9f0d758da 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditMultiDayHearingTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditMultiDayHearingTests.cs @@ -23,7 +23,7 @@ public class EditMultiDayHearingTests : HearingsControllerTests { [TestCase(false)] [TestCase(true)] - public async Task Should_update_multi_day_hearing_for_v2(bool updateFutureDays) + public async Task Should_update_multi_day_hearing(bool updateFutureDays) { // Arrange var hearingId = Guid.NewGuid(); @@ -53,7 +53,6 @@ public async Task Should_update_multi_day_hearing_for_v2(bool updateFutureDays) ScheduledDateTime = hearingInGroup.ScheduledDateTime.AddDays(1) }); } - FeatureToggle.Setup(e => e.UseV2Api()).Returns(true); // Change the judge var judge = request.JudiciaryParticipants.First(x => x.Role == "Judge"); @@ -200,7 +199,7 @@ public async Task Should_update_multi_day_hearing_for_v2(bool updateFutureDays) } [Test] - public async Task should_update_multi_day_hearing_for_v2_when_judiciary_participants_are_unchanged() + public async Task should_update_multi_day_hearing_when_judiciary_participants_are_unchanged() { // Arrange var hearingId = Guid.NewGuid(); @@ -219,7 +218,6 @@ public async Task should_update_multi_day_hearing_for_v2_when_judiciary_particip ScheduledDateTime = hearingInGroup.ScheduledDateTime }); } - FeatureToggle.Setup(e => e.UseV2Api()).Returns(true); var updatedHearing = MapUpdatedHearingV2(hearing, request); BookingsApiClient.Setup(x => x.GetHearingDetailsByIdV2Async(hearingId)).ReturnsAsync(updatedHearing); @@ -246,7 +244,7 @@ public async Task should_update_multi_day_hearing_for_v2_when_judiciary_particip } [Test] - public async Task Should_not_overwrite_data_for_future_days_when_only_specific_details_are_changed_for_v2() + public async Task Should_not_overwrite_data_for_future_days_when_only_specific_details_are_changed() { // Scenario - we have a 2 day hearing // Day 2 has been individually edited, and so has different details, participants and endpoints to Day 1 @@ -339,8 +337,6 @@ public async Task Should_not_overwrite_data_for_future_days_when_only_specific_d request.AudioRecordingRequired = day1Hearing.AudioRecordingRequired; request.UpdateFutureDays = true; - FeatureToggle.Setup(e => e.UseV2Api()).Returns(true); - var updatedHearing = MapUpdatedHearingV2(day1Hearing, request); BookingsApiClient.Setup(x => x.GetHearingDetailsByIdV2Async(hearingId)).ReturnsAsync(updatedHearing); @@ -406,7 +402,7 @@ public async Task Should_not_overwrite_data_for_future_days_when_only_specific_d } [Test] - public async Task Should_update_multi_day_hearing_when_updated_participants_and_endpoints_do_not_exist_on_future_days_for_v2() + public async Task Should_update_multi_day_hearing_when_updated_participants_and_endpoints_do_not_exist_on_future_days() { // Scenario - we have a 2 day hearing // Day 1 has been individually edited, and has additional participants and endpoints not on Day 2 @@ -463,8 +459,6 @@ public async Task Should_update_multi_day_hearing_when_updated_participants_and_ } request.UpdateFutureDays = true; - FeatureToggle.Setup(e => e.UseV2Api()).Returns(true); - var updatedHearing = MapUpdatedHearingV2(day1Hearing, request); BookingsApiClient.Setup(x => x.GetHearingDetailsByIdV2Async(hearingId)).ReturnsAsync(updatedHearing); @@ -518,7 +512,7 @@ public async Task Should_update_multi_day_hearing_when_updated_participants_and_ } [Test] - public async Task Should_remove_linked_participants_for_v2() + public async Task Should_remove_linked_participants() { // Arrange var hearingId = Guid.NewGuid(); @@ -548,8 +542,6 @@ public async Task Should_remove_linked_participants_for_v2() } request.UpdateFutureDays = true; - FeatureToggle.Setup(e => e.UseV2Api()).Returns(true); - var updatedHearing = MapUpdatedHearingV2(day1Hearing, request); BookingsApiClient.Setup(x => x.GetHearingDetailsByIdV2Async(hearingId)).ReturnsAsync(updatedHearing); @@ -576,7 +568,7 @@ public async Task Should_remove_linked_participants_for_v2() } [Test] - public async Task Should_update_multi_day_hearing_when_participant_is_new_to_edited_hearing_but_exists_on_future_days_for_v2() + public async Task Should_update_multi_day_hearing_when_participant_is_new_to_edited_hearing_but_exists_on_future_days() { // Arrange var hearingId = Guid.NewGuid(); @@ -626,8 +618,6 @@ public async Task Should_update_multi_day_hearing_when_participant_is_new_to_edi }); request.UpdateFutureDays = true; - FeatureToggle.Setup(e => e.UseV2Api()).Returns(true); - var updatedHearing = MapUpdatedHearingV2(day1Hearing, request); BookingsApiClient.Setup(x => x.GetHearingDetailsByIdV2Async(hearingId)).ReturnsAsync(updatedHearing); @@ -706,8 +696,6 @@ public async Task Should_reassign_judge_when_future_day_hearing_is_assigned_to_d newJudge.PersonalCode = Guid.NewGuid().ToString(); request.UpdateFutureDays = true; - FeatureToggle.Setup(e => e.UseV2Api()).Returns(true); - var updatedHearing = MapUpdatedHearingV2(day1Hearing, request); BookingsApiClient.Setup(x => x.GetHearingDetailsByIdV2Async(hearingId)).ReturnsAsync(updatedHearing); @@ -751,7 +739,7 @@ public async Task Should_reassign_judge_when_future_day_hearing_is_assigned_to_d } [Test] - public async Task Should_forward_not_found_from_bookings_api_for_v2() + public async Task Should_forward_not_found_from_bookings_api() { // Arrange var hearingId = Guid.NewGuid(); @@ -765,7 +753,6 @@ public async Task Should_forward_not_found_from_bookings_api_for_v2() null); BookingsApiClient.Setup(x => x.GetHearingDetailsByIdV2Async(hearingId)) .ThrowsAsync(apiException); - FeatureToggle.Setup(e => e.UseV2Api()).Returns(true); // Act var result = await Controller.EditMultiDayHearing(hearingId, request); @@ -776,7 +763,7 @@ public async Task Should_forward_not_found_from_bookings_api_for_v2() } [Test] - public async Task Should_return_bad_request_when_hearing_is_not_multi_day_for_v2() + public async Task Should_return_bad_request_when_hearing_is_not_multi_day() { // Arrange var hearingId = Guid.NewGuid(); @@ -786,8 +773,7 @@ public async Task Should_return_bad_request_when_hearing_is_not_multi_day_for_v2 var request = CreateV2EditMultiDayHearingRequest(hearing); hearing.GroupId = null; - FeatureToggle.Setup(e => e.UseV2Api()).Returns(true); - + var updatedHearing = MapUpdatedHearingV2(hearing, request); BookingsApiClient.Setup(x => x.GetHearingDetailsByIdV2Async(hearingId)).ReturnsAsync(updatedHearing); diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetHearingTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetHearingTests.cs index af2c119ec..9761a414a 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetHearingTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetHearingTests.cs @@ -148,31 +148,12 @@ public void Initialise() _mocker.Mock().Setup(x => x.GetHearingDetailsByIdAsync(It.IsAny())) .ReturnsAsync(_vhExistingHearingV1); } + [Test] public async Task Should_return_ok_status_if_hearing_id_is_valid() { // Arrange - _mocker.Mock().Setup(x => x.GetHearingDetailsByIdAsync(It.IsAny())) - .ReturnsAsync(_vhExistingHearingV1); - - // Act - var result = await _controller.GetHearingById(_v1HearingId); - - // Assert - var okRequestResult = (OkObjectResult) result; - okRequestResult.StatusCode.Should().Be(200); - - var hearing = (HearingDetailsResponse) ((OkObjectResult) result).Value; - hearing.Id.Should().Be(_vhExistingHearingV1.Id); - } - - [Test] - public async Task Should_return_ok_status_if_hearing_id_is_validV2() - { - // Arrange - _mocker.Mock().Setup(x => x.UseV2Api()) - .Returns(true); _mocker.Mock().Setup(x => x.GetHearingDetailsByIdV2Async(It.IsAny())).ReturnsAsync(_vhExistingHearingV2); @@ -186,67 +167,11 @@ public async Task Should_return_ok_status_if_hearing_id_is_validV2() var hearing = (HearingDetailsResponse) ((OkObjectResult) result).Value; hearing.Id.Should().Be(_vhExistingHearingV2.Id); } - - [Test] - public async Task Should_return_ok_status_for_multi_day_hearing_V1() - { - // Arrange - _mocker.Mock().Setup(x => x.UseV2Api()) - .Returns(false); - var groupId = _vhExistingHearingV1.Id; - _vhExistingHearingV1.GroupId = groupId; - _mocker.Mock().Setup(x => x.GetHearingDetailsByIdAsync(It.IsAny())) - .ReturnsAsync(_vhExistingHearingV1); - - var dates = new List - { - _vhExistingHearingV1.ScheduledDateTime.AddDays(1), - _vhExistingHearingV1.ScheduledDateTime.AddDays(2), - _vhExistingHearingV1.ScheduledDateTime.AddDays(3), - _vhExistingHearingV1.ScheduledDateTime.AddDays(4) - }; - var multiDayHearings = new List - { - _vhExistingHearingV1 - }; - multiDayHearings.AddRange(dates.Select(date => new BookingsApi.Contract.V1.Responses.HearingDetailsResponse - { - Id = Guid.NewGuid(), - ScheduledDateTime = date, - ScheduledDuration = _vhExistingHearingV1.ScheduledDuration, - GroupId = groupId, - Status = BookingStatus.Created - })); - // Set some to cancelled and failed so we can test they are filtered out - multiDayHearings[2].Status = BookingStatus.Cancelled; - multiDayHearings[3].Status = BookingStatus.Failed; - _mocker.Mock().Setup(x => x.GetHearingsByGroupIdAsync(groupId)) - .ReturnsAsync(multiDayHearings); - - // Act - var result = await _controller.GetHearingById(_v1HearingId); - - // Assert - var okRequestResult = (OkObjectResult) result; - okRequestResult.StatusCode.Should().Be(200); - - var response = (HearingDetailsResponse) ((OkObjectResult) result).Value; - var expectedActiveHearingsInGroup = multiDayHearings - .Where(h => - h.Status != BookingStatus.Cancelled && - h.Status != BookingStatus.Failed) - .ToList(); - var expectedHearingLastDay = expectedActiveHearingsInGroup[^1]; - response.MultiDayHearingLastDayScheduledDateTime.Should().Be(expectedHearingLastDay.ScheduledDateTime); - response.HearingsInGroup.Should().BeEquivalentTo(multiDayHearings.Select(x => x.Map())); - } [Test] - public async Task Should_return_ok_status_for_multi_day_hearing_V2() + public async Task Should_return_ok_status_for_multi_day_hearing() { // Arrange - _mocker.Mock().Setup(x => x.UseV2Api()) - .Returns(true); var groupId = _vhExistingHearingV2.Id; _vhExistingHearingV2.GroupId = groupId; _mocker.Mock().Setup(x => x.GetHearingDetailsByIdV2Async(It.IsAny())) @@ -296,61 +221,11 @@ public async Task Should_return_ok_status_for_multi_day_hearing_V2() } [Test] - public async Task Should_return_ok_status_for_cancelled_multi_day_hearing_V1() - { - // Scenario - all days in the multi day hearing are cancelled - - // Arrange - _mocker.Mock().Setup(x => x.UseV2Api()) - .Returns(false); - var groupId = _vhExistingHearingV1.Id; - _vhExistingHearingV1.GroupId = groupId; - _vhExistingHearingV1.Status = BookingStatus.Cancelled; - _mocker.Mock().Setup(x => x.GetHearingDetailsByIdAsync(It.IsAny())) - .ReturnsAsync(_vhExistingHearingV1); - - var dates = new List - { - _vhExistingHearingV1.ScheduledDateTime.AddDays(1), - _vhExistingHearingV1.ScheduledDateTime.AddDays(2), - _vhExistingHearingV1.ScheduledDateTime.AddDays(3), - _vhExistingHearingV1.ScheduledDateTime.AddDays(4), - }; - var multiDayHearings = new List - { - _vhExistingHearingV1 - }; - multiDayHearings.AddRange(dates.Select(date => new BookingsApi.Contract.V1.Responses.HearingDetailsResponse - { - Id = Guid.NewGuid(), - ScheduledDateTime = date, - ScheduledDuration = _vhExistingHearingV2.ScheduledDuration, - GroupId = groupId, - Status = BookingStatus.Cancelled - })); - _mocker.Mock().Setup(x => x.GetHearingsByGroupIdAsync(groupId)) - .ReturnsAsync(multiDayHearings); - - // Act - var result = await _controller.GetHearingById(_v1HearingId); - - // Assert - var okRequestResult = (OkObjectResult) result; - okRequestResult.StatusCode.Should().Be(200); - - var response = (HearingDetailsResponse) ((OkObjectResult) result).Value; - response.MultiDayHearingLastDayScheduledDateTime.Should().BeNull(); - response.HearingsInGroup.Should().BeEquivalentTo(multiDayHearings.Select(x => x.Map())); - } - - [Test] - public async Task Should_return_ok_status_for_cancelled_multi_day_hearing_V2() + public async Task Should_return_ok_status_for_cancelled_multi_day_hearing() { // Scenario - all days in the multi day hearing are cancelled // Arrange - _mocker.Mock().Setup(x => x.UseV2Api()) - .Returns(true); var groupId = _vhExistingHearingV2.Id; _vhExistingHearingV2.GroupId = groupId; _vhExistingHearingV2.Status = BookingStatusV2.Cancelled; diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetStatusHearingTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetStatusHearingTests.cs index 173dc79d1..78f8ab92c 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetStatusHearingTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetStatusHearingTests.cs @@ -263,7 +263,7 @@ public async Task Should_return_badRequest_if_hearing_failed_to_fail() } [Test] - public async Task Should_return_ok_status_with_success_when_V2flag_on() + public async Task Should_return_ok_status_with_success() { // Arrange ConferenceDetailsResponse conferenceResponse = new() @@ -277,7 +277,6 @@ public async Task Should_return_ok_status_with_success_when_V2flag_on() } }; - _featureFlag.Setup(x => x.UseV2Api()).Returns(true); _conferenceDetailsServiceMock.Setup(x => x.GetConferenceDetailsByHearingId(_guid, false)) .ReturnsAsync(conferenceResponse); _vhExistingHearingV2.Status = BookingsApi.Contract.V2.Enums.BookingStatusV2.Created; diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/ReferenceDataControllerTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/ReferenceDataControllerTests.cs index 84054e8c0..70381c958 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/ReferenceDataControllerTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/ReferenceDataControllerTests.cs @@ -47,8 +47,6 @@ public void Should_return_a_list_of_venues() [Test] public async Task Should_return_all_hearing_types_and_case_types_where_hearing_type_is_empty() { - - _featureTogglesMock.Setup(x => x.UseV2Api()).Returns(true); // Arrange var includeDeleted = true; _userIdentityMock.Setup(x => x.IsATeamLead()) @@ -66,17 +64,12 @@ public async Task Should_return_all_hearing_types_and_case_types_where_hearing_t _bookingsApiClientMock.Verify(x => x.GetCaseTypesAsync(includeDeleted), Times.Once); } - [TestCase(true)] - [TestCase(false)] - public async Task Should_return_participants_roles(bool refDataFeatureToggle) + [Test] + public async Task Should_return_participants_roles() { - _featureTogglesMock.Setup(x => x.ReferenceDataToggle()).Returns(refDataFeatureToggle); List listTypes; - if(refDataFeatureToggle) - listTypes = new List { new CaseRoleResponseV2 { Name = "type1" } }; - else - listTypes = new List { new CaseRoleResponse { Name = "type1" } }; - SetTestCase(listTypes, refDataFeatureToggle); + listTypes = new List { new CaseRoleResponseV2 { Name = "type1" } }; + SetTestCase(listTypes, true); var response = await _controller.GetParticipantRoles("type1"); response.Should().NotBeNull(); diff --git a/AdminWebsite/AdminWebsite/Configuration/FeatureToggles.cs b/AdminWebsite/AdminWebsite/Configuration/FeatureToggles.cs index a25f7548e..000d8bf78 100644 --- a/AdminWebsite/AdminWebsite/Configuration/FeatureToggles.cs +++ b/AdminWebsite/AdminWebsite/Configuration/FeatureToggles.cs @@ -10,7 +10,7 @@ public interface IFeatureToggles { public bool Dom1Enabled(); public bool ReferenceDataToggle(); - public bool UseV2Api(); + //public bool UseV2Api(); public bool HrsEnabled(); } @@ -21,7 +21,7 @@ public class FeatureToggles : IFeatureToggles private const string LdUser = "vh-admin-web"; private const string Dom1EnabledToggleKey = "dom1"; private const string ReferenceDataToggleKey = "reference-data"; - private const string UseV2ApiToggleKey = "use-bookings-api-v2"; + //private const string UseV2ApiToggleKey = "use-bookings-api-v2"; private const string HrsFeatureToggleKey = "hrs-integration"; @@ -48,10 +48,10 @@ public bool HrsEnabled() return GetBoolValueWithKey(HrsFeatureToggleKey); } - public bool UseV2Api() - { - return GetBoolValueWithKey(UseV2ApiToggleKey); - } + // public bool UseV2Api() + // { + // return GetBoolValueWithKey(UseV2ApiToggleKey); + // } private bool GetBoolValueWithKey(string key) { diff --git a/AdminWebsite/AdminWebsite/Controllers/HearingsController.cs b/AdminWebsite/AdminWebsite/Controllers/HearingsController.cs index 88a13fc5f..2f54650a9 100644 --- a/AdminWebsite/AdminWebsite/Controllers/HearingsController.cs +++ b/AdminWebsite/AdminWebsite/Controllers/HearingsController.cs @@ -129,27 +129,14 @@ private async Task BookNewHearing(BookingDetailsRequest newBookingReques _logger.LogInformation("BookNewHearing - Attempting to send booking request to Booking API"); - if (_featureToggles.UseV2Api()) - { - var newBookingRequestV2 = newBookingRequest.MapToV2(); - - var hearingDetailsResponse = await _bookingsApiClient.BookNewHearingWithCodeAsync(newBookingRequestV2); - - hearingId = hearingDetailsResponse.Id; - - response = hearingDetailsResponse.Map(); - } - else - { - var newBookingRequestV1 = newBookingRequest.MapToV1(); - - var hearingDetailsResponse = await _bookingsApiClient.BookNewHearingAsync(newBookingRequestV1); - - hearingId = hearingDetailsResponse.Id; - - response = hearingDetailsResponse.Map(); - } + var newBookingRequestV2 = newBookingRequest.MapToV2(); + + var hearingDetailsResponse = await _bookingsApiClient.BookNewHearingWithCodeAsync(newBookingRequestV2); + hearingId = hearingDetailsResponse.Id; + + response = hearingDetailsResponse.Map(); + _logger.LogInformation("BookNewHearing - Successfully booked hearing {Hearing}", hearingId); return response; @@ -411,26 +398,14 @@ public async Task CancelMultiDayHearing(Guid hearingId, CancelMul private async Task GetHearing(Guid hearingId) { - if (_featureToggles.UseV2Api()) - { - var responseV2 = await _bookingsApiClient.GetHearingDetailsByIdV2Async(hearingId); - return responseV2.Map(); - } - - var responseV1 = await _bookingsApiClient.GetHearingDetailsByIdAsync(hearingId); - return responseV1.Map(); + var responseV2 = await _bookingsApiClient.GetHearingDetailsByIdV2Async(hearingId); + return responseV2.Map(); } private async Task MapHearingToUpdate(Guid hearingId) { - if (_featureToggles.UseV2Api()) - { - var updatedHearing2 = await _bookingsApiClient.GetHearingDetailsByIdV2Async(hearingId); - return updatedHearing2.Map(); - } - - var updatedHearing1 = await _bookingsApiClient.GetHearingDetailsByIdAsync(hearingId); - return updatedHearing1.Map(); + var updatedHearing2 = await _bookingsApiClient.GetHearingDetailsByIdV2Async(hearingId); + return updatedHearing2.Map(); } private async Task UpdateHearing(EditHearingRequest request, Guid hearingId, HearingDetailsResponse originalHearing) @@ -451,19 +426,10 @@ private async Task UpdateHearing(EditHearingRequest request, Guid hearingId, Hea request.AudioRecordingRequired = originalHearing.AudioRecordingRequired; } - if (_featureToggles.UseV2Api()) - { - var updateHearingRequestV2 = HearingUpdateRequestMapper.MapToV2(request, _userIdentity.GetUserIdentityName()); - await _bookingsApiClient.UpdateHearingDetails2Async(hearingId, updateHearingRequestV2); - await UpdateParticipantsV2(hearingId, request.Participants, request.Endpoints, originalHearing); - await UpdateJudiciaryParticipants(hearingId, request.JudiciaryParticipants, originalHearing); - } - else - { - var updateHearingRequestV1 = HearingUpdateRequestMapper.MapToV1(request, _userIdentity.GetUserIdentityName()); - await _bookingsApiClient.UpdateHearingDetailsAsync(hearingId, updateHearingRequestV1); - await UpdateParticipantsV1(hearingId, request.Participants, request.Endpoints, originalHearing); - } + var updateHearingRequestV2 = HearingUpdateRequestMapper.MapToV2(request, _userIdentity.GetUserIdentityName()); + await _bookingsApiClient.UpdateHearingDetails2Async(hearingId, updateHearingRequestV2); + await UpdateParticipantsV2(hearingId, request.Participants, request.Endpoints, originalHearing); + await UpdateJudiciaryParticipants(hearingId, request.JudiciaryParticipants, originalHearing); } private async Task UpdateMultiDayHearing(EditMultiDayHearingRequest request, Guid hearingId, Guid groupId) @@ -973,26 +939,14 @@ public async Task GetHearingById(Guid hearingId) try { HearingDetailsResponse hearingResponse; - if (_featureToggles.UseV2Api()) - { - var response = await _bookingsApiClient.GetHearingDetailsByIdV2Async(hearingId); - ICollection groupedHearings = null; - if (response.GroupId != null) - { - groupedHearings = await _bookingsApiClient.GetHearingsByGroupIdV2Async(response.GroupId.Value); - } - hearingResponse = response.Map(groupedHearings); - } - else + var response = await _bookingsApiClient.GetHearingDetailsByIdV2Async(hearingId); + ICollection groupedHearings = null; + if (response.GroupId != null) { - var response = await _bookingsApiClient.GetHearingDetailsByIdAsync(hearingId); - ICollection groupedHearings = null; - if (response.GroupId != null) - { - groupedHearings = await _bookingsApiClient.GetHearingsByGroupIdAsync(response.GroupId.Value); - } - hearingResponse = response.Map(groupedHearings); + groupedHearings = await _bookingsApiClient.GetHearingsByGroupIdV2Async(response.GroupId.Value); } + hearingResponse = response.Map(groupedHearings); + return Ok(hearingResponse); } catch (BookingsApiException e) @@ -1194,16 +1148,8 @@ public async Task GetTelephoneConferenceIdById(Guid hearingId) private IEnumerable ParticipantsNeedVHAccounts(List allParticipants) { - IEnumerable participantsNeedVHAccounts; - if (_featureToggles.UseV2Api()) - { - participantsNeedVHAccounts = allParticipants.Where(x => x.UserRoleName == RoleNames.Individual || x.UserRoleName == RoleNames.Representative); - } - else - { - participantsNeedVHAccounts = allParticipants.Where(x => x.UserRoleName != RoleNames.Judge); - } - + var participantsNeedVHAccounts = allParticipants.Where(x => x.UserRoleName == RoleNames.Individual || x.UserRoleName == RoleNames.Representative); + return participantsNeedVHAccounts; } } diff --git a/AdminWebsite/AdminWebsite/Controllers/ReferenceDataController.cs b/AdminWebsite/AdminWebsite/Controllers/ReferenceDataController.cs index 3a2ef521b..1377e89dc 100644 --- a/AdminWebsite/AdminWebsite/Controllers/ReferenceDataController.cs +++ b/AdminWebsite/AdminWebsite/Controllers/ReferenceDataController.cs @@ -60,13 +60,12 @@ public async Task>> GetHearingTypes([Fro Code = hearingType.Code } )).ToList(); - if (_featureToggles.UseV2Api()) - result.AddRange(caseTypes.Where(ct => !ct.HearingTypes.Any()) - .Select(caseType => new HearingTypeResponse - { - Group = caseType.Name, - ServiceId = caseType.ServiceId - })); + result.AddRange(caseTypes.Where(ct => !ct.HearingTypes.Any()) + .Select(caseType => new HearingTypeResponse + { + Group = caseType.Name, + ServiceId = caseType.ServiceId + })); return Ok(result); } diff --git a/AdminWebsite/AdminWebsite/Services/HearingsService.cs b/AdminWebsite/AdminWebsite/Services/HearingsService.cs index 5ab1e0f16..52c16ca0b 100644 --- a/AdminWebsite/AdminWebsite/Services/HearingsService.cs +++ b/AdminWebsite/AdminWebsite/Services/HearingsService.cs @@ -107,7 +107,7 @@ public Task ProcessNewParticipant( { // Add a new participant // Map the request except the username - if (participant.CaseRoleName == RoleNames.Judge || (_featureToggles.UseV2Api() && participant.HearingRoleName is RoleNames.PanelMember or RoleNames.Winger)) + if (participant.CaseRoleName == RoleNames.Judge || (participant.HearingRoleName is RoleNames.PanelMember or RoleNames.Winger)) { if (hearing.Participants != null && hearing.Participants.Exists(p => p.ContactEmail.Equals(participant.ContactEmail) && removedParticipantIds.TrueForAll(removedParticipantId => removedParticipantId != p.Id))) From c4c3c1d91caaf3eac0974b832bb7d5c75c1cb356 Mon Sep 17 00:00:00 2001 From: marcogagliardi Date: Mon, 10 Jun 2024 08:57:59 +0100 Subject: [PATCH 03/25] removed V2 flag --- .../ClientApp/src/app/services/launch-darkly.service.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.ts index 51b67d2c3..b15d54e83 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.ts @@ -9,7 +9,6 @@ export const FeatureFlags = { hrsIntegration: 'hrs-integration', referenceData: 'reference-data', audioSearch: 'hide-audio-search-tile', - useV2Api: 'use-bookings-api-v2', multiDayBookingEnhancements: 'multi-day-booking-enhancements' }; From e27e54c1715a2ba131753308b638d1b0416fcff9 Mon Sep 17 00:00:00 2001 From: marcogagliardi Date: Mon, 10 Jun 2024 09:04:44 +0100 Subject: [PATCH 04/25] removed hide-audio-search-tile --- .../ClientApp/src/app/app-routing.module.ts | 3 +- .../ClientApp/src/app/app.module.ts | 4 +- .../app/dashboard/dashboard.component.spec.ts | 17 +------- .../src/app/dashboard/dashboard.component.ts | 7 +--- .../app/security/audio-search.guard.spec.ts | 42 ------------------- .../src/app/security/audio-search.guard.ts | 27 ------------ .../src/app/services/launch-darkly.service.ts | 1 - 7 files changed, 5 insertions(+), 96 deletions(-) delete mode 100644 AdminWebsite/AdminWebsite/ClientApp/src/app/security/audio-search.guard.spec.ts delete mode 100644 AdminWebsite/AdminWebsite/ClientApp/src/app/security/audio-search.guard.ts diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/app-routing.module.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/app-routing.module.ts index 522f37899..78a6403e7 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/app-routing.module.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/app-routing.module.ts @@ -15,7 +15,6 @@ import { AdminGuard } from './security/guards/admin.guard'; import { VhOfficerAdminGuard } from './security/guards/vh-officer-admin.guard'; import { LoginComponent } from './security/login.component'; import { ReformLoginComponent } from './security/reform-login.component'; -import { AudioSearchGuard } from './security/audio-search.guard'; import { ManageTeamFeatureGuard } from './security/guards/manage-team-feature.guard'; import { AuthGuard } from './security/guards/auth.guard'; @@ -31,7 +30,7 @@ export const routes: Routes = [ { path: 'error', component: ErrorComponent }, { path: 'unsupported-browser', component: UnsupportedBrowserComponent }, { path: 'change-password', component: ChangePasswordComponent, canActivate: [AuthGuard, AdminGuard] }, - { path: 'get-audio-file', component: GetAudioFileComponent, canActivate: [AuthGuard, AdminGuard, AudioSearchGuard] }, + { path: 'get-audio-file', component: GetAudioFileComponent, canActivate: [AuthGuard, AdminGuard] }, { path: 'delete-participant', component: DeleteParticipantSearchComponent, canActivate: [AuthGuard, AdminGuard] }, { path: 'edit-participant-search', component: EditParticipantSearchComponent, canActivate: [AuthGuard, AdminGuard] }, { path: 'edit-participant', component: EditParticipantComponent, canActivate: [AuthGuard, AdminGuard] }, diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/app.module.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/app.module.ts index 2ffefec7f..4c9a20477 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/app.module.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/app.module.ts @@ -41,7 +41,6 @@ import { LastMinuteAmendmentsGuard } from './security/guards/last-minute-amendme import { AdminGuard } from './security/guards/admin.guard'; import { AuthGuard } from './security/guards/auth.guard'; import { ReformLoginComponent } from './security/reform-login.component'; -import { AudioSearchGuard } from './security/audio-search.guard'; import { ManageTeamFeatureGuard } from './security/guards/manage-team-feature.guard'; export function loadConfig(configService: ConfigService) { @@ -100,8 +99,7 @@ export function loadConfig(configService: ConfigService) { PageTrackerService, AppInsightsLogger, WindowRef, - ManageTeamFeatureGuard, - AudioSearchGuard + ManageTeamFeatureGuard ], exports: [UnallocatedHearingsComponent], bootstrap: [AppComponent] diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/dashboard/dashboard.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/dashboard/dashboard.component.spec.ts index b839cb2ba..37ef44d7c 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/dashboard/dashboard.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/dashboard/dashboard.component.spec.ts @@ -16,7 +16,6 @@ describe('DashboardComponent', () => { const loggerSpy = jasmine.createSpyObj('Logger', ['error', 'debug', 'warn']); beforeEach(waitForAsync(() => { - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.audioSearch).and.returnValue(of(false)); launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.dom1Integration).and.returnValue(of(false)); TestBed.configureTestingModule({ @@ -151,7 +150,7 @@ describe('DashboardComponent', () => { await component.ngOnInit(); expect(component.showWorkAllocation).toBeFalsy(); }); - it('should not show link to audio file if feature is switched on', async () => { + it('should not show link to audio file', async () => { userIdentitySpy.getUserInformation.and.returnValue( of( new UserProfileResponse({ @@ -160,22 +159,8 @@ describe('DashboardComponent', () => { ) ); - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.audioSearch).and.returnValue(of(true)); await component.ngOnInit(); expect(component.showAudioFileLink).toBeFalsy(); }); - it('should show link to audio file if feature is switched off', async () => { - userIdentitySpy.getUserInformation.and.returnValue( - of( - new UserProfileResponse({ - is_vh_officer_administrator_role: true - }) - ) - ); - - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.audioSearch).and.returnValue(of(false)); - await component.ngOnInit(); - expect(component.showAudioFileLink).toBeTruthy(); - }); }); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/dashboard/dashboard.component.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/dashboard/dashboard.component.ts index b25e5ecd4..515b7f9f0 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/dashboard/dashboard.component.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/dashboard/dashboard.component.ts @@ -25,7 +25,6 @@ export class DashboardComponent implements OnInit, OnDestroy { showBooking = false; showWorkAllocation = false; dom1Feature = false; - audioSearchFeature: boolean; showManageTeam = false; showAudioFileLink = false; @@ -33,16 +32,14 @@ export class DashboardComponent implements OnInit, OnDestroy { destroyed$ = new Subject(); ngOnInit() { - const audioSearchFlag$ = this.launchDarklyService.getFlag(FeatureFlags.audioSearch).pipe(takeUntil(this.destroyed$)); const dom1FeatureFlag$ = this.launchDarklyService.getFlag(FeatureFlags.dom1Integration).pipe(takeUntil(this.destroyed$)); - combineLatest([audioSearchFlag$, dom1FeatureFlag$]).subscribe(([audioSearchFlag, dom1FeatureFlag]) => { - this.audioSearchFeature = audioSearchFlag; + combineLatest([dom1FeatureFlag$]).subscribe(([dom1FeatureFlag]) => { this.dom1Feature = dom1FeatureFlag; lastValueFrom(this.userIdentityService.getUserInformation()).then(profile => { this.showCheckList = profile.is_vh_officer_administrator_role; this.showWorkAllocation = profile.is_vh_team_leader; - this.showAudioFileLink = this.showCheckList && !this.audioSearchFeature; + this.showAudioFileLink = this.showCheckList; this.showBooking = profile.is_case_administrator || profile.is_vh_officer_administrator_role; this.showManageTeam = profile.is_vh_team_leader && this.dom1Feature; this.logger.debug(`${this.loggerPrefix} Landed on dashboard`, { diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/security/audio-search.guard.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/security/audio-search.guard.spec.ts deleted file mode 100644 index 39a2d6377..000000000 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/security/audio-search.guard.spec.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { fakeAsync, TestBed } from '@angular/core/testing'; -import { Router } from '@angular/router'; -import { Logger } from '../services/logger'; -import { AudioSearchGuard } from './audio-search.guard'; -import { LaunchDarklyService } from '../services/launch-darkly.service'; -import { MockLaunchDarklyService } from '../testing/mocks/MockLaunchDarklyService'; - -describe('audiosearchguard', () => { - let audioSearchGuard: AudioSearchGuard; - let launchDarklyService; - const loggerSpy = jasmine.createSpyObj('Logger', ['error', 'debug', 'warn']); - const router = { - navigate: jasmine.createSpy('navigate') - }; - - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ - AudioSearchGuard, - { provide: LaunchDarklyService, useClass: MockLaunchDarklyService }, - { provide: Router, useValue: router }, - { provide: Logger, useValue: loggerSpy } - ] - }).compileComponents(); - launchDarklyService = TestBed.inject(LaunchDarklyService); - audioSearchGuard = TestBed.inject(AudioSearchGuard); - }); - - describe('when toggle off with successful authentication', () => { - it('canActivate should return true', () => { - launchDarklyService.setAudioSearchFlag(false); - audioSearchGuard.canActivate().subscribe(result => expect(result).toBeTruthy()); - }); - }); - - describe('when toggle is on with successful authentication', () => { - it('canActivate should return false', fakeAsync(() => { - launchDarklyService.setAudioSearchFlag(true); - audioSearchGuard.canActivate().subscribe(result => expect(result).toBeFalsy()); - })); - }); -}); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/security/audio-search.guard.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/security/audio-search.guard.ts deleted file mode 100644 index 2ef964f91..000000000 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/security/audio-search.guard.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Router } from '@angular/router'; -import { Observable } from 'rxjs'; -import { map } from 'rxjs/operators'; -import { PageUrls } from '../shared/page-url.constants'; -import { Logger } from '../services/logger'; -import { FeatureFlags, LaunchDarklyService } from '../services/launch-darkly.service'; - -@Injectable() -export class AudioSearchGuard { - private readonly loggerPrefix = '[AudioSearchGuard] -'; - constructor(private launchDarklyService: LaunchDarklyService, private router: Router, private logger: Logger) {} - - canActivate(): Observable { - return this.launchDarklyService.getFlag(FeatureFlags.audioSearch).pipe( - map(result => { - if (result) { - this.logger.warn(`${this.loggerPrefix} - canActivate isAuthorized: false`); - this.router.navigate([`/${PageUrls.Login}`]); - return false; - } - this.logger.debug(`${this.loggerPrefix} - canActivate isAuthorized: true`); - return true; - }) - ); - } -} diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.ts index b15d54e83..97886ca4d 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.ts @@ -8,7 +8,6 @@ export const FeatureFlags = { dom1Integration: 'dom1', hrsIntegration: 'hrs-integration', referenceData: 'reference-data', - audioSearch: 'hide-audio-search-tile', multiDayBookingEnhancements: 'multi-day-booking-enhancements' }; From b32f5593180949a46beddd3407a1b560a1870386 Mon Sep 17 00:00:00 2001 From: marcogagliardi Date: Mon, 10 Jun 2024 09:12:02 +0100 Subject: [PATCH 05/25] removed hrs-integration --- .../Controllers/AudioPlatformControllerTests.cs | 4 +--- .../src/app/services/launch-darkly.service.ts | 1 - .../AdminWebsite/Configuration/FeatureToggles.cs | 14 -------------- .../Controllers/AudioPlatformController.cs | 9 +-------- 4 files changed, 2 insertions(+), 26 deletions(-) diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/AudioPlatformControllerTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/AudioPlatformControllerTests.cs index 107cfe0bc..92c5ff25b 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/AudioPlatformControllerTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/AudioPlatformControllerTests.cs @@ -41,7 +41,6 @@ public async Task Should_return_ok() }; _videoApiClientMock.Setup(x => x.GetAudioRecordingLinkAsync(It.IsAny())).ReturnsAsync(audioResponse); - _featureTogglesMock.Setup(x => x.HrsEnabled()).Returns(false); var result = await _controller.GetAudioRecordingLinkAsync(It.IsAny()); @@ -55,7 +54,7 @@ public async Task Should_return_ok() } [Test] - public async Task Should_return_hrs_file_format_with_hrs_toggle_on() + public async Task Should_return_hrs_file_format() { var audioResponse = new AudioRecordingResponse { @@ -72,7 +71,6 @@ public async Task Should_return_hrs_file_format_with_hrs_toggle_on() }; _videoApiClientMock.Setup(x => x.GetAudioRecordingLinkAsync(It.IsAny())).ReturnsAsync(audioResponse); - _featureTogglesMock.Setup(x => x.HrsEnabled()).Returns(true); _bookingsApiClientMock.Setup(x => x.GetHearingDetailsByIdV2Async(It.IsAny())).ReturnsAsync(hearing); var result = await _controller.GetAudioRecordingLinkAsync(It.IsAny()); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.ts index 97886ca4d..62e1b58ca 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.ts @@ -6,7 +6,6 @@ import { first, map } from 'rxjs/operators'; export const FeatureFlags = { dom1Integration: 'dom1', - hrsIntegration: 'hrs-integration', referenceData: 'reference-data', multiDayBookingEnhancements: 'multi-day-booking-enhancements' }; diff --git a/AdminWebsite/AdminWebsite/Configuration/FeatureToggles.cs b/AdminWebsite/AdminWebsite/Configuration/FeatureToggles.cs index 000d8bf78..79e3b7c28 100644 --- a/AdminWebsite/AdminWebsite/Configuration/FeatureToggles.cs +++ b/AdminWebsite/AdminWebsite/Configuration/FeatureToggles.cs @@ -10,8 +10,6 @@ public interface IFeatureToggles { public bool Dom1Enabled(); public bool ReferenceDataToggle(); - //public bool UseV2Api(); - public bool HrsEnabled(); } public class FeatureToggles : IFeatureToggles @@ -21,8 +19,6 @@ public class FeatureToggles : IFeatureToggles private const string LdUser = "vh-admin-web"; private const string Dom1EnabledToggleKey = "dom1"; private const string ReferenceDataToggleKey = "reference-data"; - //private const string UseV2ApiToggleKey = "use-bookings-api-v2"; - private const string HrsFeatureToggleKey = "hrs-integration"; public FeatureToggles(string sdkKey, string environmentName) @@ -43,16 +39,6 @@ public bool ReferenceDataToggle() return GetBoolValueWithKey(ReferenceDataToggleKey); } - public bool HrsEnabled() - { - return GetBoolValueWithKey(HrsFeatureToggleKey); - } - - // public bool UseV2Api() - // { - // return GetBoolValueWithKey(UseV2ApiToggleKey); - // } - private bool GetBoolValueWithKey(string key) { if (!_ldClient.Initialized) diff --git a/AdminWebsite/AdminWebsite/Controllers/AudioPlatformController.cs b/AdminWebsite/AdminWebsite/Controllers/AudioPlatformController.cs index 234fe9ff5..400803d4a 100644 --- a/AdminWebsite/AdminWebsite/Controllers/AudioPlatformController.cs +++ b/AdminWebsite/AdminWebsite/Controllers/AudioPlatformController.cs @@ -50,14 +50,7 @@ public async Task GetAudioRecordingLinkAsync(Guid hearingId) try { var requestKey = ""; - if (_featureToggles.HrsEnabled()) - { - requestKey = await GetAudioHrsFileName(hearingId); - } - else - { - requestKey = hearingId.ToString(); - } + requestKey = await GetAudioHrsFileName(hearingId); var response = await _videoAPiClient.GetAudioRecordingLinkAsync(requestKey); return Ok(new HearingAudioRecordingResponse { AudioFileLinks = response.AudioFileLinks }); From a8c68e059e97871e01059b2076b652568dab67ae Mon Sep 17 00:00:00 2001 From: marcogagliardi Date: Mon, 10 Jun 2024 09:52:50 +0100 Subject: [PATCH 06/25] Update dashboard.component.spec.ts --- .../ClientApp/src/app/dashboard/dashboard.component.spec.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/dashboard/dashboard.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/dashboard/dashboard.component.spec.ts index 37ef44d7c..86ce6c863 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/dashboard/dashboard.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/dashboard/dashboard.component.spec.ts @@ -162,5 +162,4 @@ describe('DashboardComponent', () => { await component.ngOnInit(); expect(component.showAudioFileLink).toBeFalsy(); }); - }); From f924833606d7cc0d95c79d58d960849e802e3f58 Mon Sep 17 00:00:00 2001 From: marcogagliardi Date: Mon, 10 Jun 2024 15:14:34 +0100 Subject: [PATCH 07/25] removed unit test for V1 --- .../HearingsController/BookNewHearingTests.cs | 257 ------ .../CancelMultiDayHearingTests.cs | 49 - .../HearingsController/EditHearingTests.cs | 843 ------------------ .../EditMultiDayHearingTests.cs | 48 - .../HearingsController/GetHearingTests.cs | 22 - .../GetStatusHearingTests.cs | 109 +-- .../HearingsController/PostHearingTests.cs | 163 +--- .../ReferenceDataControllerTests.cs | 26 +- .../src/app/services/launch-darkly.service.ts | 1 - .../Configuration/FeatureToggles.cs | 7 - .../Controllers/ReferenceDataController.cs | 25 +- 11 files changed, 15 insertions(+), 1535 deletions(-) diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/BookNewHearingTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/BookNewHearingTests.cs index 240f25c9c..ff839ce5d 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/BookNewHearingTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/BookNewHearingTests.cs @@ -50,263 +50,6 @@ public void Setup() _controller = _mocker.Create(); } - [Test] - public async Task Should_book_hearing_for_single_day() - { - // Arrange - var bookingDetails = InitHearingForTest(); - - var bookingRequest = new BookHearingRequest - { - BookingDetails = bookingDetails - }; - - var hearingDetailsResponse = HearingResponseBuilder.Build() - .WithEndPoints(2) - .WithParticipant("Representative", "username1@hmcts.net") - .WithParticipant("Individual", "fname2.lname2@hmcts.net") - .WithParticipant("Individual", "fname3.lname3@hmcts.net") - .WithParticipant("Judicial Office Holder", "fname4.lname4@hmcts.net") - .WithParticipant("Staff Member","staff.member@hmcts.net") - .WithParticipant("Judge", "judge.fudge@hmcts.net"); - _mocker.Mock().Setup(x => x.BookNewHearingAsync(It.IsAny())) - .ReturnsAsync(hearingDetailsResponse); - - - _mocker.Mock().Setup(x => x.GetUserIdentityName()).Returns(_expectedUserIdentityName); - - // Act - var result = await _controller.Post(bookingRequest); - - // Assert - result.Result.Should().BeOfType(); - var createdObjectResult = (CreatedResult) result.Result; - createdObjectResult.StatusCode.Should().Be(201); - createdObjectResult.Value.Should().BeEquivalentTo(hearingDetailsResponse, - options => options.ExcludingMissingMembers()); - - bookingDetails.Participants.Exists(x => string.IsNullOrWhiteSpace(x.Username)).Should().BeFalse(); - - bookingDetails.CreatedBy.Should().Be(_expectedUserIdentityName); - - _mocker.Mock().Verify(x => x.AssignEndpointDefenceAdvocates(It.IsAny>(), It.Is>(x => x.SequenceEqual(bookingDetails.Participants.AsReadOnly()))), Times.Once); - - _mocker.Mock().Verify(x => x.BookNewHearingAsync(It.IsAny()), Times.Once); - } - - [Test] - public async Task Should_book_hearing_without_judge() - { - // Arrange - var bookingDetails = InitHearingForTest(); - //remove judge - bookingDetails.Participants.Remove(bookingDetails.Participants.Find(e => e.HearingRoleName == "Judge")); - var bookingRequest = new BookHearingRequest - { - BookingDetails = bookingDetails - }; - var hearingDetailsResponse = HearingResponseBuilder.Build() - .WithEndPoints(2) - .WithParticipant("Representative", "username1@hmcts.net") - .WithParticipant("Individual", "fname2.lname2@hmcts.net") - .WithParticipant("Individual", "fname3.lname3@hmcts.net") - .WithParticipant("Judicial Office Holder", "fname4.lname4@hmcts.net") - .WithParticipant("Staff Member", "staff.member@hmcts.net"); - - _mocker.Mock().Setup(x => x.BookNewHearingAsync(It.IsAny())) - .ReturnsAsync(hearingDetailsResponse); - - _mocker.Mock().Setup(x => x.GetUserIdentityName()).Returns(_expectedUserIdentityName); - - // Act - var result = await _controller.Post(bookingRequest); - - // Assert - result.Result.Should().BeOfType(); - var createdObjectResult = (CreatedResult) result.Result; - createdObjectResult.StatusCode.Should().Be(201); - createdObjectResult.Value.Should().BeEquivalentTo(hearingDetailsResponse, - options => options.ExcludingMissingMembers()); - - bookingDetails.Participants.Exists(x => string.IsNullOrWhiteSpace(x.Username)).Should().BeFalse(); - - bookingDetails.CreatedBy.Should().Be(_expectedUserIdentityName); - - _mocker.Mock().Verify(x => x.AssignEndpointDefenceAdvocates(It.IsAny>(), It.Is>(x => x.SequenceEqual(bookingDetails.Participants.AsReadOnly()))), Times.Once); - - _mocker.Mock().Verify(x => x.BookNewHearingAsync(It.IsAny()), Times.Once); - } - - [Test] - public async Task Should_book_hearing_for_single_day_without_endpoints() - { - // Arrange - var bookingDetails = InitHearingForTest(); - bookingDetails.Endpoints = null; - - var bookingRequest = new BookHearingRequest - { - BookingDetails = bookingDetails - }; - - var hearingDetailsResponse = HearingResponseBuilder.Build() - .WithEndPoints(2) - .WithParticipant("Representative", "username1@hmcts.net") - .WithParticipant("Individual", "fname2.lname2@hmcts.net") - .WithParticipant("Individual", "fname3.lname3@hmcts.net") - .WithParticipant("Judicial Office Holder", "fname4.lname4@hmcts.net") - .WithParticipant("Judge", "judge.fudge@hmcts.net"); - _mocker.Mock().Setup(x => x.BookNewHearingAsync(It.IsAny())) - .ReturnsAsync(hearingDetailsResponse); - - _mocker.Mock().Setup(x => x.GetUserIdentityName()).Returns(_expectedUserIdentityName); - - // Act - var result = await _controller.Post(bookingRequest); - - // Assert - result.Result.Should().BeOfType(); - var createdObjectResult = (CreatedResult) result.Result; - createdObjectResult.StatusCode.Should().Be(201); - createdObjectResult.Value.Should().BeEquivalentTo(hearingDetailsResponse, - options => options.ExcludingMissingMembers()); - - bookingDetails.CreatedBy.Should().Be(_expectedUserIdentityName); - bookingDetails.Participants.Exists(x => string.IsNullOrWhiteSpace(x.Username)).Should().BeFalse(); - - _mocker.Mock().Verify(x => x.AssignEndpointDefenceAdvocates(It.IsAny>(), It.Is>(x => x.SequenceEqual(bookingDetails.Participants.AsReadOnly()))), Times.Never); - - _mocker.Mock().Verify(x => x.BookNewHearingAsync(It.IsAny()), Times.Once); - } - - [Test] - public async Task Should_book_hearing_for_multi_day() - { - // Arrange - const int expectedMultiDayHearingDuration = 3; - DateTime expectedStartDate = new DateTime(2021, 5, 10, 0, 0, 1, DateTimeKind.Utc); - DateTime expectedEndDate = expectedStartDate.AddDays(expectedMultiDayHearingDuration - 1); - - var bookingDetails = InitHearingForTest(); - - var bookingRequest = new BookHearingRequest - { - IsMultiDay = true, - MultiHearingDetails = new MultiHearingRequest - { - StartDate = expectedStartDate, - EndDate = expectedEndDate - }, - BookingDetails = bookingDetails - }; - - _mocker.Mock().Setup(x => x.GetAdUserIdForUsername(It.IsAny())).ReturnsAsync(Guid.NewGuid().ToString()); - - _mocker.Mock().Setup(x => x.GetUserIdentityName()).Returns(_expectedUserIdentityName); - - // setup response - var hearingDetailsResponse = HearingResponseBuilder.Build() - .WithEndPoints(2) - .WithParticipant("Representative", "username1@hmcts.net") - .WithParticipant("Individual", "fname2.lname2@hmcts.net") - .WithParticipant("Individual", "fname3.lname3@hmcts.net") - .WithParticipant("Judicial Office Holder", "fname4.lname4@hmcts.net") - .WithParticipant("Judge", "judge.fudge@hmcts.net"); - - _mocker.Mock() - .Setup(x => x.BookNewHearingAsync(It.IsAny())) - .ReturnsAsync(hearingDetailsResponse); - - // Act - var result = await _controller.Post(bookingRequest); - - // Assert - result.Result.Should().BeOfType(); - var createdObjectResult = (CreatedResult) result.Result; - createdObjectResult.StatusCode.Should().Be(201); - createdObjectResult.Value.Should().BeEquivalentTo(hearingDetailsResponse, - options => options.ExcludingMissingMembers()); - - bookingDetails.CreatedBy.Should().Be(_expectedUserIdentityName); - bookingDetails.Participants.Exists(x => string.IsNullOrWhiteSpace(x.Username)).Should().BeFalse(); - - _mocker.Mock().Verify(x => x.AssignEndpointDefenceAdvocates(It.IsAny>(), It.Is>(x => x.SequenceEqual(bookingDetails.Participants.AsReadOnly()))), Times.Once); - - _mocker.Mock().Verify(x => x.BookNewHearingAsync(It.IsAny()), Times.Once); - } - - [Test] - public async Task Should_catch_bookings_api_exceptions_and_return_bad_request_if_that_was_the_status_code() - { - // Arrange - var bookingDetails = InitHearingForTest(); - - var bookingRequest = new BookHearingRequest - { - BookingDetails = bookingDetails - }; - - _mocker.Mock().Setup(x => x.GetAdUserIdForUsername(It.IsAny())).ReturnsAsync(Guid.NewGuid().ToString()); - - const string key = "ScheduledDateTime"; - const string errorMessage = "ScheduledDateTime cannot be in the past"; - var validationProblemDetails = new ValidationProblemDetails(new Dictionary - { - {key, [errorMessage] }, - }); - _mocker.Mock().Setup(x => x.BookNewHearingAsync(It.IsAny())) - .Throws(ClientException.ForBookingsAPIValidation(validationProblemDetails)); - - // Act - var result = await _controller.Post(bookingRequest); - - // Assert - result.Result.Should().NotBeNull(); - var objectResult = (ObjectResult)result.Result; - - var validationProblems = (ValidationProblemDetails)objectResult.Value; - validationProblems.Should().NotBeNull(); - validationProblems!.Errors.ContainsKey(key).Should().BeTrue(); - validationProblems.Errors[key][0].Should().Be(errorMessage); - - _mocker.Mock().Verify(x => x.AssignEndpointDefenceAdvocates(It.IsAny>(), It.Is>(x => x.SequenceEqual(bookingDetails.Participants.AsReadOnly()))), Times.Once); - - _mocker.Mock().Verify(x => x.BookNewHearingAsync(It.IsAny()), Times.Once); - } - - [Test] - public async Task Should_handle_failed_booking_request() - { - var bookingDetails = InitHearingForTest(); - - var bookingRequest = new BookHearingRequest - { - BookingDetails = bookingDetails - }; - - var hearingDetailsResponse = - HearingResponseBuilder.Build() - .WithParticipant("Judge", "manual.judge@hmcts.net"); - - hearingDetailsResponse.Status = BookingStatus.Failed; - - _mocker.Mock().Setup(x => x.BookNewHearingAsync(It.IsAny())) - .ReturnsAsync(hearingDetailsResponse); - - _mocker.Mock().Setup(x => x.GetUserIdentityName()).Returns(_expectedUserIdentityName); - - var result = await _controller.Post(bookingRequest); - - var response = ((ObjectResult)result.Result)?.Value as HearingDetailsResponse; - - response.Status.Should().Be((AdminWebsite.Contracts.Enums.BookingStatus)BookingStatus.Failed); - - ((ObjectResult)result.Result).StatusCode.Should().Be(201); - - _mocker.Mock().Verify(x => x.BookNewHearingAsync(It.IsAny()), Times.Once); - } - - private BookingDetailsRequest InitHearingForTest() { // request with existing person, new user, existing user in AD but not in persons table diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/CancelMultiDayHearingTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/CancelMultiDayHearingTests.cs index 094e5777c..b06f32d87 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/CancelMultiDayHearingTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/CancelMultiDayHearingTests.cs @@ -139,55 +139,6 @@ public async Task Should_return_bad_request_when_hearing_is_not_multi_day() errors.Should().BeEquivalentTo(validationProblemDetails.Errors); } - [Test] - public async Task Should_forward_bad_request_from_bookings_api() - { - // Arrange - var hearingId = Guid.NewGuid(); - var request = new CancelMultiDayHearingRequest(); - var validationProblemDetails = new ValidationProblemDetails(new Dictionary - { - {"id", ["Please provide a valid id"] } - }); - var apiException = new BookingsApiException("BadRequest", - (int)HttpStatusCode.BadRequest, - "Please provide a valid id", - null, - validationProblemDetails, - null); - BookingsApiClient.Setup(x => x.GetHearingDetailsByIdAsync(hearingId)) - .ThrowsAsync(apiException); - - // Act - var result = await Controller.CancelMultiDayHearing(hearingId, request); - - var objectResult = (ObjectResult)result; - var validationProblems = (ValidationProblemDetails)objectResult.Value; - - var errors = validationProblems.Errors; - errors.Should().BeEquivalentTo(validationProblemDetails.Errors); - } - - [Test] - public void Should_forward_unhandled_error_from_bookings_api() - { - // Arrange - var hearingId = Guid.NewGuid(); - var request = new CancelMultiDayHearingRequest(); - var errorMessage = "Unexpected error for unit test"; - var apiException = new BookingsApiException("Server Error", - (int) HttpStatusCode.InternalServerError, - "Server Error", null, errorMessage, null); - BookingsApiClient.Setup(x => x.GetHearingDetailsByIdAsync(hearingId)) - .ThrowsAsync(apiException); - - // Act & Assert - var response = Controller.CancelMultiDayHearing(hearingId, request); - - ((ObjectResult) response.Result).StatusCode.Should().Be(500); - - } - private static CancelMultiDayHearingRequest CreateRequest() => new() { diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditHearingTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditHearingTests.cs index f0ceee950..54cc0de8c 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditHearingTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditHearingTests.cs @@ -410,143 +410,6 @@ public async Task Should_return_bad_request_if_no_participants_are_given() errors["participants"].Should().Contain( "Please provide at least one participant"); } - [Test] - public async Task Should_return_not_found_if_hearing_is_missing() - { - _bookingsApiClient.Setup(x => x.GetHearingDetailsByIdAsync(It.IsAny())) - .Throws(ClientException.ForBookingsAPI(HttpStatusCode.NotFound)); - - var result = await _controller.EditHearing(_validId, _addNewParticipantRequest); - var notFoundResult = (NotFoundObjectResult)result.Result; - notFoundResult.Value.Should().Be($"No hearing with id found [{_validId}]"); - } - - [Test] - public void Should_throw_if_hearing_exception_is_not_of_type_not_found() - { - _bookingsApiClient.Setup(x => x.GetHearingDetailsByIdAsync(It.IsAny())) - .Throws(ClientException.ForBookingsAPI(HttpStatusCode.InternalServerError)); - - Assert.ThrowsAsync(async () => await _controller.EditHearing(_validId, _addNewParticipantRequest)); - } - - [Test] - public async Task Should_return_bad_request_if_editing_hearing_fails_with_bad_request_status_code() - { - //Arrange - _addNewParticipantRequest.Participants = new List(); - - _bookingsApiClient.Setup(x => x.GetHearingDetailsByIdAsync(It.IsAny())) - .ReturnsAsync(_existingHearingWithLinkedParticipants); - var validationProblemDetails = new ValidationProblemDetails(new Dictionary - { - {"Hearing", ["Cannot remove a participant from hearing that is close to start time"] }, - }); - - _bookingsApiClient.Setup(x => x.UpdateHearingParticipantsAsync(It.IsAny(), It.IsAny())) - .Throws(ClientException.ForBookingsAPIValidation(validationProblemDetails)); - - //Act - var response = await _controller.EditHearing(_validId, _addNewParticipantRequest); - - //Assert - response.Result.Should().BeOfType(); - } - - [Test] - public void Should_throw_if_editing_hearing_fails_with_non_bad_request() - { - - if (true) - { - //execute - } - - if (false) - { - //execute - } - - //Arrange - _addNewParticipantRequest.Participants = new List(); - - _bookingsApiClient.Setup(x => x.GetHearingDetailsByIdAsync(It.IsAny())) - .ReturnsAsync(_existingHearingWithLinkedParticipants); - _bookingsApiClient.Setup(x => x.UpdateHearingParticipantsAsync(It.IsAny(), It.IsAny())) - .Throws(ClientException.ForBookingsAPI(HttpStatusCode.InternalServerError)); - - //Act/Assert - - var response = _controller.EditHearing(_validId, _addNewParticipantRequest); - - ((ObjectResult)response.Result.Result).StatusCode.Should().Be(500); - } - - [TestCase("Confirmed By")] - [TestCase("")] - public async Task Should_add_panel_members_for_a_hearing(string confirmedBy) - { - //Arrange - var updatedHearing = new HearingDetailsResponse - { - Participants = _updatedExistingParticipantHearingOriginal.Participants, - Cases = _updatedExistingParticipantHearingOriginal.Cases, - CaseTypeName = "Unit Test", - ConfirmedBy = confirmedBy - }; - - _addNewParticipantRequest.Participants = new List {new EditParticipantRequest - { - HearingRoleName = RoleNames.PanelMember, - ContactEmail = "new.contactactemail@domain.net", - DisplayName = "new.displayName@domain.net", - CaseRoleName = RoleNames.PanelMember - } }; - - _bookingsApiClient.SetupSequence(x => x.GetHearingDetailsByIdAsync(It.IsAny())) - .ReturnsAsync(_updatedExistingParticipantHearingOriginal) - .ReturnsAsync(updatedHearing) - .ReturnsAsync(updatedHearing); - - //Act - var result = await _controller.EditHearing(_validId, _addNewParticipantRequest); - - //Assert - ((OkObjectResult)result.Result).StatusCode.Should().Be(200); - _bookingsApiClient.Verify(x => x.UpdateHearingDetailsAsync(It.IsAny(), It.IsAny())); - } - - [Test] - public async Task Should_return_updated_hearing1() - { - var updatedHearing = new HearingDetailsResponse - { - Id = _validId, - Participants = _updatedExistingParticipantHearingOriginal.Participants, - Cases = _updatedExistingParticipantHearingOriginal.Cases, - CaseTypeName = "Unit Test" - }; - updatedHearing.Participants.Add(new ParticipantResponse - { - Id = Guid.NewGuid(), - ContactEmail = "new@domain.net", - Username = "new@domain.net", - UserRoleName = "Individual" - }); - - _bookingsApiClient.SetupSequence(x => x.GetHearingDetailsByIdAsync(It.IsAny())) - .ReturnsAsync(_updatedExistingParticipantHearingOriginal) - .ReturnsAsync(updatedHearing) - .ReturnsAsync(updatedHearing); - var result = await _controller.EditHearing(_validId, _addNewParticipantRequest); - var hearing = (AdminWebsite.Contracts.Responses.HearingDetailsResponse)((OkObjectResult)result.Result).Value; - hearing.Id.Should().Be(_updatedExistingParticipantHearingOriginal.Id); - _bookingsApiClient.Verify(x => x.UpdateHearingDetailsAsync(It.IsAny(), - It.Is(u => - u.Cases.Count > 0)), - Times.Once); - } - [Test] public async Task Should_return_updated_hearing2() { @@ -943,141 +806,6 @@ private void AssertJudiciaryJudgeReassigned( It.IsAny>()), Times.Never); } - - [Test] - public async Task Should_pass_on_bad_request_from_bookings_api() - { - var validationProblemDetails = new ValidationProblemDetails(new Dictionary - { - {"Hearing", ["Cannot remove a participant from hearing that is close to start time"] }, - }); - - _bookingsApiClient.Setup(x => - x.UpdateHearingDetailsAsync(It.IsAny(), It.IsAny())) - .ThrowsAsync(ClientException.ForBookingsAPIValidation(validationProblemDetails)); - - var response = await _controller.EditHearing(_validId, _addNewParticipantRequest); - response.Result.Should().BeOfType(); - } - - [Test] - public async Task Should_pass_on_not_found_request_from_bookings_api() - { - _bookingsApiClient.Setup(x => x.GetHearingDetailsByIdAsync(It.IsAny())) - .ThrowsAsync(ClientException.ForBookingsAPI(HttpStatusCode.NotFound)); - - var response = await _controller.EditHearing(_validId, _addNewParticipantRequest); - response.Result.Should().BeOfType(); - } - - [Test] - public async Task Should_replace_judge_based_on_email() - { - var existingJudgeId = Guid.NewGuid(); - _updatedExistingParticipantHearingOriginal.Participants.Add(new ParticipantResponse - { - FirstName = "Existing", - LastName = "Judge", - ContactEmail = "existing@domain.net", - Username = "existing@domain.net", - CaseRoleName = "Judge", - UserRoleName = "Judge", - HearingRoleName = "Judge", - Id = existingJudgeId - }); - - const string newJudgeEmail = "new@domain.net"; - _addNewParticipantRequest.Participants.Add(new EditParticipantRequest - { - CaseRoleName = "Judge", - HearingRoleName = "Judge", - FirstName = "New", - LastName = "Judge", - ContactEmail = newJudgeEmail - }); - - var newPats = _updatedExistingParticipantHearingOriginal.Participants.Where(x => x.Id != existingJudgeId) - .ToList(); - newPats.Add(new ParticipantResponse - { - Id = Guid.NewGuid(), - ContactEmail = "new@domain.net", - Username = "new@domain.net", - UserRoleName = "Individual" - }); - newPats.Add(new ParticipantResponse - { - FirstName = "New", - LastName = "Judge", - ContactEmail = newJudgeEmail, - Username = newJudgeEmail, - UserRoleName = "Judge", - CaseRoleName = "Judge", - HearingRoleName = "Judge", - }); - var updatedHearing = new HearingDetailsResponse - { - Participants = newPats, - Cases = _updatedExistingParticipantHearingOriginal.Cases, - CaseTypeName = "Unit Test" - }; - - _bookingsApiClient.SetupSequence(x => x.GetHearingDetailsByIdAsync(It.IsAny())) - .ReturnsAsync(_updatedExistingParticipantHearingOriginal) - .ReturnsAsync(updatedHearing) - .ReturnsAsync(updatedHearing); - - var response = await _controller.EditHearing(_validId, _addNewParticipantRequest); - response.Result.Should().BeOfType(); - - _bookingsApiClient.Verify(x => x.UpdateHearingParticipantsAsync(_validId, - It.Is( - participants => participants.NewParticipants.Any(p => p.Username == newJudgeEmail))), Times.Once); - _bookingsApiClient.Verify(x => x.UpdateHearingDetailsAsync(It.IsAny(), - It.Is(u => - u.Cases.Count > 0)), - Times.Once); - } - - [Test] - public async Task Should_add_endpoint_if_new_endpoint_is_added_to_endpoint_list() - { - _addEndpointToHearingRequest.Participants = new List(); - _bookingsApiClient.Setup(x => x.GetHearingDetailsByIdAsync(It.IsAny())) - .ReturnsAsync(_existingHearingWithEndpointsOriginal); - var result = await _controller.EditHearing(_validId, _addEndpointToHearingRequest); - ((OkObjectResult)result.Result).StatusCode.Should().Be(200); - _bookingsApiClient.Verify( - x => x.AddEndPointToHearingAsync(It.IsAny(), It.IsAny()), Times.Once); - _bookingsApiClient.Verify(x => x.UpdateHearingDetailsAsync(It.IsAny(), - It.Is(u => - u.Cases.Count > 0)), - Times.Once); - _bookingsApiClient.Verify( - x => x.UpdateDisplayNameForEndpointAsync(It.IsAny(), It.IsAny(), - It.IsAny()), Times.Never); - _bookingsApiClient.Verify( - x => x.RemoveEndPointFromHearingAsync(It.IsAny(), It.IsAny()), Times.Never); - } - - [Test] - public async Task Should_update_endpoint_if_an_endpoint_is_updates_in_endpoint_list() - { - _bookingsApiClient.Setup(x => x.GetHearingDetailsByIdAsync(It.IsAny())) - .ReturnsAsync(_existingHearingWithEndpointsOriginal); - var result = await _controller.EditHearing(_validId, _editEndpointOnHearingRequestWithJudge); - ((OkObjectResult)result.Result).StatusCode.Should().Be(200); - _bookingsApiClient.Verify(x => x.AddEndPointToHearingAsync(It.IsAny(), It.IsAny()), Times.Never); - _bookingsApiClient.Verify(x => x.UpdateHearingDetailsAsync(It.IsAny(), - It.Is(u => - u.Cases.Count > 0)), Times.Once); - _bookingsApiClient.Verify( - x => x.UpdateDisplayNameForEndpointAsync(It.IsAny(), It.IsAny(), - It.IsAny()), Times.Once); - _bookingsApiClient.Verify(x => x.RemoveEndPointFromHearingAsync(It.IsAny(), It.IsAny()), - Times.Never); - - } [Test] public async Task Should_update_endpoint_to_be_linked_to_new_defence_advocate_when_endpoint_is_not_currently_linked() @@ -1131,576 +859,5 @@ public async Task Should_update_endpoint_to_be_linked_to_new_defence_advocate_wh r.DefenceAdvocateContactEmail == newParticipantDefenceAdvocate.ContactEmail)), Times.Exactly(expectedUpdatedEndpointCount)); } - - [Test] - public async Task Should_remove_endpoint_if_endpoint_is_removed_from_the_endpoint_list() - { - _bookingsApiClient.Setup(x => x.GetHearingDetailsByIdAsync(It.IsAny())) - .ReturnsAsync(_existingHearingWithEndpointsOriginal); - var result = await _controller.EditHearing(_validId, _removeEndpointOnHearingRequest); - ((OkObjectResult)result.Result).StatusCode.Should().Be(200); - - _bookingsApiClient.Verify( - x => x.AddEndPointToHearingAsync(It.IsAny(), It.IsAny()), Times.Never); - - _bookingsApiClient.Verify(x => x.RemoveEndPointFromHearingAsync(It.IsAny(), It.IsAny()), - Times.Once); - - _bookingsApiClient.Verify(x => x.UpdateHearingDetailsAsync(It.IsAny(), - It.Is(u => - u.Cases.Count > 0)), Times.Once); - - _bookingsApiClient.Verify( - x => x.UpdateDisplayNameForEndpointAsync(It.IsAny(), It.IsAny(), - It.IsAny()), Times.Never); - } - - [Test] - public async Task If_Judge_Added_To_Hearing_And_Saved_Should_Auto_confirm_booking() - { - // arrange - original hearing - var hearingId = _updatedExistingParticipantHearingOriginal.Id; - var originalHearing = _updatedExistingParticipantHearingOriginal.Duplicate(); - var updatedHearing = _updatedExistingParticipantHearingOriginal.Duplicate(); - updatedHearing.Participants.Add(new ParticipantResponse{ - DisplayName = "newJudge", - HearingRoleName = RoleNames.Judge, - CaseRoleName = RoleNames.Judge, - UserRoleName = RoleNames.Judge, - ContactEmail = "judge@moj.gov.uk" - }); - originalHearing.Status = BookingStatus.Booked; - _bookingsApiClient.Setup(x => x.GetHearingsByGroupIdAsync(originalHearing.GroupId.Value)) - .ReturnsAsync(new List {originalHearing}); - _bookingsApiClient.SetupSequence(x => x.GetHearingDetailsByIdAsync(hearingId)) - .ReturnsAsync(originalHearing) - .ReturnsAsync(updatedHearing); - // arrange - request - var request = new EditHearingRequest(); - request.Case = new EditCaseRequest(); - request.Participants.Add(new EditParticipantRequest - { - DisplayName = "newJudge", - HearingRoleName = RoleNames.Judge, - CaseRoleName = RoleNames.Judge, - ContactEmail = "judge@moj.gov.uk" - }); - //Act - var result = await _controller.EditHearing(hearingId, request); - ((OkObjectResult)result.Result).StatusCode.Should().Be(200); - - } - - [Test] - public async Task Should_not_update_DisplayName_if_no_matching_endpoint_exists_in_list() - { - _existingHearingWithEndpointsOriginal.Endpoints[0].Id = Guid.NewGuid(); - _existingHearingWithEndpointsOriginal.Endpoints[0].DisplayName = "data1-edit"; - _existingHearingWithEndpointsOriginal.Endpoints[0].DefenceAdvocateId = null; - _existingHearingWithEndpointsOriginal.Endpoints[3].DisplayName = "data4-edit"; - _existingHearingWithEndpointsOriginal.Endpoints[3].DefenceAdvocateId = null; - - _bookingsApiClient.Setup(x => x.GetHearingDetailsByIdAsync(It.IsAny())) - .ReturnsAsync(_existingHearingWithEndpointsOriginal); - - var result = await _controller.EditHearing(_validId, _addEndpointToHearingRequest); - - ((OkObjectResult)result.Result).StatusCode.Should().Be(200); - - _bookingsApiClient.Verify( - x => x.AddEndPointToHearingAsync(It.IsAny(), It.IsAny()), Times.Once); - - // The old Endpoints[0] has no matching Id now, and so it will be removed - _bookingsApiClient.Verify( - x => x.RemoveEndPointFromHearingAsync(It.IsAny(), It.IsAny()), Times.Once); - - _bookingsApiClient.Verify(x => x.UpdateHearingDetailsAsync(It.IsAny(), - It.Is(u => - u.Cases.Count > 0)), Times.Once); - - // Endpoints[3] has had their details changed, and so will be updated - _bookingsApiClient.Verify( - x => x.UpdateDisplayNameForEndpointAsync(It.IsAny(), It.IsAny(), - It.IsAny()), Times.Once); - } - - [Test] - public async Task Should_process_participants() - { - //Arrange - var existingLinkedParticipantOne = - _existingHearingWithLinkedParticipants.Participants.Find(x => x.LinkedParticipants.Count > 0); - var existingLinkedParticipantTwo = - _existingHearingWithLinkedParticipants.Participants - .SingleOrDefault(x => x.Id == existingLinkedParticipantOne.LinkedParticipants[0].LinkedId); - - var editPrefix = "Edited"; - var updatedExistingLinkedParticipantOne = new EditParticipantRequest - { - Id = existingLinkedParticipantOne.Id, - ContactEmail = existingLinkedParticipantOne.ContactEmail, - FirstName = editPrefix + existingLinkedParticipantOne.FirstName, - LastName = editPrefix + existingLinkedParticipantOne.LastName, - LinkedParticipants = new List - { - new LinkedParticipant - { - LinkedId = existingLinkedParticipantTwo.Id, - LinkedParticipantContactEmail = existingLinkedParticipantTwo.ContactEmail, - ParticipantContactEmail = existingLinkedParticipantOne.ContactEmail - } - } - }; - - var updatedExistingLinkedParticipantTwo = new EditParticipantRequest - { - Id = existingLinkedParticipantTwo.Id, - ContactEmail = existingLinkedParticipantTwo.ContactEmail, - FirstName = editPrefix + existingLinkedParticipantTwo.FirstName, - LastName = editPrefix + existingLinkedParticipantTwo.LastName, - LinkedParticipants = new List - { - new LinkedParticipant - { - LinkedId = existingLinkedParticipantOne.Id, - LinkedParticipantContactEmail = existingLinkedParticipantTwo.ContactEmail, - ParticipantContactEmail = existingLinkedParticipantTwo.ContactEmail - } - } - }; - - var newParticipant = new EditParticipantRequest - { - ContactEmail = "ContactEmail", - FirstName = "Hi", - LastName = "Hello", - }; - - _addNewParticipantRequest.Participants = new List - { - updatedExistingLinkedParticipantOne, - updatedExistingLinkedParticipantTwo, - newParticipant - }; - - var removedParticipantIds = _existingHearingWithLinkedParticipants.Participants - .Where(p => _addNewParticipantRequest.Participants.TrueForAll(rp => rp.Id != p.Id)).Select(x => x.Id).ToList(); - - _bookingsApiClient.Setup(x => x.GetHearingDetailsByIdAsync(It.IsAny())) - .ReturnsAsync(_existingHearingWithLinkedParticipants); - - //Act - var response = await _controller.EditHearing(_validId, _addNewParticipantRequest); - response.Result.Should().BeOfType(); - - Func, List, bool> areRemovedParticipantIdsCorrect = (List listOne, List listTwo) => - { - foreach (var guid in listOne) - { - if (!listTwo.Contains(guid)) - return false; - } - - return true; - }; - - //Assert - _bookingsApiClient.Verify(x => x.UpdateHearingParticipantsAsync(_validId, - It.Is(participants => - participants.NewParticipants.Count == 1 - && participants.NewParticipants[0].ContactEmail == newParticipant.ContactEmail - && participants.NewParticipants[0].FirstName == newParticipant.FirstName - && participants.NewParticipants[0].LastName == newParticipant.LastName - - && participants.RemovedParticipantIds.Count == removedParticipantIds.Count - && areRemovedParticipantIdsCorrect(participants.RemovedParticipantIds, removedParticipantIds) - - && participants.ExistingParticipants.Count == 2 - - && participants.LinkedParticipants.Count == 1 - && participants.LinkedParticipants[0].ParticipantContactEmail == existingLinkedParticipantOne.ContactEmail - && participants.LinkedParticipants[0].LinkedParticipantContactEmail == existingLinkedParticipantTwo.ContactEmail - )), Times.Once); - } - - [Test] - public async Task Should_add_a_new_participant_and_link_to_existing_interpreter_when_editing_a_hearing() - { - var newUserContactEmail = "newindividual4.user@email.com"; - var interpreter = - _existingHearingWithLinkedParticipants.Participants.First(p => - p.HearingRoleName.Equals("interpreter",StringComparison.CurrentCultureIgnoreCase)); - - var partipant4 = Guid.NewGuid(); - - var _existingHearingWithNewLinkedParticipants = new HearingDetailsResponse - { - Id = _validId, - GroupId = _validId, - Cases = _existingHearingWithLinkedParticipants.Cases, - CaseTypeName = "case type", - HearingTypeName = "hearing type", - Participants = new List - { - new ParticipantResponse - { - Id = _existingHearingWithLinkedParticipants.Participants[0].Id, CaseRoleName = "judge", HearingRoleName = "hearingrole", - ContactEmail = "judge.user@email.com", UserRoleName = "Judge", FirstName = "Judge", - LinkedParticipants = null - }, - new ParticipantResponse - { - Id = _existingHearingWithLinkedParticipants.Participants[1].Id, CaseRoleName = "caserole", HearingRoleName = "litigant in person", - ContactEmail = "individual.user@email.com", UserRoleName = "Individual", - FirstName = "testuser1", LinkedParticipants = null - }, - new ParticipantResponse - { - Id = interpreter.Id, CaseRoleName = "caserole", HearingRoleName = "interpreter", - ContactEmail = "interpreter.user@email.com", UserRoleName = "Individual", - FirstName = "testuser1", - LinkedParticipants = new List - { - new LinkedParticipantResponse - {Type = LinkedParticipantType.Interpreter, LinkedId = partipant4} - } - }, - new ParticipantResponse - { - Id = partipant4, CaseRoleName = "caserole", HearingRoleName = "litigant in person", - ContactEmail = "individual4.user@email.com", UserRoleName = "Individual4", - FirstName = "testuser4", LinkedParticipants = null - } - }, - ScheduledDateTime = DateTime.UtcNow.AddHours(3), - OtherInformation = "|JudgeEmail|judge@email.com|JudgePhone|0123454678" - }; - - _bookingsApiClient.Setup(x => x.GetHearingDetailsByIdAsync(It.IsAny())).ReturnsAsync(_existingHearingWithNewLinkedParticipants); - - - var addParticipantLinksToHearingRequest = new EditHearingRequest - { - Case = new EditCaseRequest { Name = "Case", Number = "123" }, - Participants = new List - { - new EditParticipantRequest - { - Id = _existingHearingWithLinkedParticipants.Participants[0].Id, CaseRoleName = "judge", HearingRoleName = "hearingrole", - ContactEmail = "judge.user@email.com", FirstName = "Judge", TelephoneNumber = "003" - }, - new EditParticipantRequest - { - Id = _existingHearingWithLinkedParticipants.Participants[1].Id, CaseRoleName = "caserole", HearingRoleName = "litigant in person", - ContactEmail = "individual.user@email.com", - FirstName = "testuser1", TelephoneNumber = "001" - }, - new EditParticipantRequest - { - Id = partipant4, CaseRoleName = "caserole", HearingRoleName = "litigant in person", - ContactEmail = "individual4.user@email.com", - FirstName = "testuser4", TelephoneNumber = "000" - }, - new EditParticipantRequest - { - CaseRoleName = "caserole", HearingRoleName = "litigant in person", - ContactEmail = "newindividual4.user@email.com", DisplayName = "NewIndividual4", FirstName = "NewIndividual4", - LastName = "newIndividual4", TelephoneNumber = "000", - }, - new EditParticipantRequest - { - Id = interpreter.Id, - CaseRoleName = "caserole", HearingRoleName = "interpreter", - ContactEmail = "interpreter.user@email.com", DisplayName = "newUser", FirstName = "firstName", - LastName = "lastName", TelephoneNumber = "000", - LinkedParticipants = new List - { - new LinkedParticipant - { - ParticipantContactEmail = "interpreter.user@email.com", - LinkedParticipantContactEmail = newUserContactEmail, - Type = AdminWebsite.Contracts.Enums.LinkedParticipantType.Interpreter - } - } - } - }, - OtherInformation = "|JudgeEmail|judge@email.com|JudgePhone|0123454678" - }; - - var result = await _controller.EditHearing(_validId, addParticipantLinksToHearingRequest); - - ((OkObjectResult)result.Result).StatusCode.Should().Be(200); - - _bookingsApiClient.Verify( - x => x.UpdateHearingParticipantsAsync(It.IsAny(), It.Is(x => x.LinkedParticipants.Any(x => x.LinkedParticipantContactEmail == newUserContactEmail))), Times.Once); - - _bookingsApiClient.Verify(x => x.UpdateHearingDetailsAsync(It.IsAny(), - It.Is(u => u.Cases.Count > 0)), Times.Once); - } - - [Test] - public async Task Should_create_a_new_judge_and_set_username_to_contact_email() - { - var _existingHearing = new HearingDetailsResponse - { - Id = _validId, - GroupId = _validId, - Cases = _existingHearingWithLinkedParticipants.Cases, - CaseTypeName = "case type", - HearingTypeName = "hearing type", - Participants = new List(), - ScheduledDateTime = DateTime.UtcNow.AddHours(3) - }; - - _bookingsApiClient.Setup(x - => x.GetHearingDetailsByIdAsync(It.IsAny())).ReturnsAsync(_existingHearing); - - var addParticipantLinksToHearingRequest = new EditHearingRequest - { - Case = new EditCaseRequest { Name = "Case", Number = "123" }, - Participants = new List - { - new EditParticipantRequest - { - CaseRoleName = "Judge", - HearingRoleName = "Judge", - ContactEmail = "judge@email.com", - FirstName = "Judge", - TelephoneNumber = "0123454678" - } - }, - OtherInformation = "|JudgeEmail|notify_judge@email.com|JudgePhone|9876" - }; - - var result = await _controller.EditHearing(_validId, addParticipantLinksToHearingRequest); - - ((OkObjectResult)result.Result).StatusCode.Should().Be(200); - - _bookingsApiClient.Verify(x - => x.UpdateHearingDetailsAsync(It.IsAny(), - It.Is(uhpr => HearingRequestValidation(uhpr)))); - - _bookingsApiClient.Verify(x - => x.UpdateHearingParticipantsAsync(It.IsAny(), - It.Is(uhpr => JudgeRequestValidation(uhpr)))); - } - - private static bool HearingRequestValidation(UpdateHearingRequest request) - { - request.OtherInformation.Should().Be("|JudgeEmail|notify_judge@email.com|JudgePhone|9876"); - return true; - } - - private static bool JudgeRequestValidation(UpdateHearingParticipantsRequest request) - { - request.NewParticipants[0].Username.Should().Be("judge@email.com"); - request.NewParticipants[0].ContactEmail.Should().Be("judge@email.com"); - request.NewParticipants[0].TelephoneNumber.Should().Be("0123454678"); - return true; - } - - [Test] - public async Task Returns_Valid_When_Linked_Contact_Email_Is_Null_When_Adding_A_New_Participant_To_Existing_Hearing() - { - var linkedParticipantEmail = "individual4.user@email.com"; - var interpreter = - _existingHearingWithLinkedParticipants.Participants.First(p => - p.HearingRoleName.Equals("interpreter", StringComparison.CurrentCultureIgnoreCase)); - - var partipant4 = Guid.NewGuid(); - - var _existingHearingWithNewLinkedParticipants = new HearingDetailsResponse - { - Id = _validId, - GroupId = _validId, - Cases = _existingHearingWithLinkedParticipants.Cases, - CaseTypeName = "case type", - HearingTypeName = "hearing type", - Participants = new List - { - new ParticipantResponse - { - Id = _existingHearingWithLinkedParticipants.Participants[0].Id, CaseRoleName = "judge", HearingRoleName = "hearingrole", - ContactEmail = "judge.user@email.com", UserRoleName = "Judge", FirstName = "Judge", - LinkedParticipants = null - }, - new ParticipantResponse - { - Id = _existingHearingWithLinkedParticipants.Participants[1].Id, CaseRoleName = "caserole", HearingRoleName = "litigant in person", - ContactEmail = "individual.user@email.com", UserRoleName = "Individual", - FirstName = "testuser1", LinkedParticipants = null - }, - new ParticipantResponse - { - Id = interpreter.Id, CaseRoleName = "caserole", HearingRoleName = "interpreter", - ContactEmail = "interpreter.user@email.com", UserRoleName = "Individual", - FirstName = "testuser1", - LinkedParticipants = new List - { - new LinkedParticipantResponse - {Type = LinkedParticipantType.Interpreter, LinkedId = partipant4} - } - }, - new ParticipantResponse - { - Id = partipant4, CaseRoleName = "caserole", HearingRoleName = "litigant in person", - ContactEmail = linkedParticipantEmail, UserRoleName = "Individual4", - FirstName = "testuser4", LinkedParticipants = null - } - }, - ScheduledDateTime = DateTime.UtcNow.AddHours(3), - OtherInformation = "" - }; - - _bookingsApiClient.Setup(x => x.GetHearingDetailsByIdAsync(It.IsAny())).ReturnsAsync(_existingHearingWithNewLinkedParticipants); - - - var addParticipantLinksToHearingRequest = new EditHearingRequest - { - Case = new EditCaseRequest { Name = "Case", Number = "123" }, - Participants = new List - { - new EditParticipantRequest - { - Id = _existingHearingWithLinkedParticipants.Participants[0].Id, CaseRoleName = "judge", HearingRoleName = "hearingrole", - ContactEmail = "judge.user@email.com", FirstName = "Judge", TelephoneNumber = "003" - }, - new EditParticipantRequest - { - Id = _existingHearingWithLinkedParticipants.Participants[1].Id, CaseRoleName = "caserole", HearingRoleName = "litigant in person", - ContactEmail = "individual.user@email.com", - FirstName = "testuser1", TelephoneNumber = "001" - }, - new EditParticipantRequest - { - Id = partipant4, CaseRoleName = "caserole", HearingRoleName = "litigant in person", - ContactEmail = "individual4.user@email.com", - FirstName = "testuser4", TelephoneNumber = "000" - }, - new EditParticipantRequest - { - CaseRoleName = "caserole", HearingRoleName = "litigant in person", - ContactEmail = "newindividual4.user@email.com", DisplayName = "NewIndividual4", FirstName = "NewIndividual4", - LastName = "newIndividual4", TelephoneNumber = "000", - }, - new EditParticipantRequest - { - Id = interpreter.Id, - CaseRoleName = "caserole", HearingRoleName = "interpreter", - ContactEmail = "interpreter.user@email.com", DisplayName = "newUser", FirstName = "firstName", - LastName = "lastName", TelephoneNumber = "000", - LinkedParticipants = new List - { - new LinkedParticipant - { - LinkedId = partipant4, - Type = AdminWebsite.Contracts.Enums.LinkedParticipantType.Interpreter, - LinkedParticipantContactEmail = null - } - } - } - }, - OtherInformation = "" - }; - - var result = await _controller.EditHearing(_validId, addParticipantLinksToHearingRequest); - - ((OkObjectResult)result.Result).StatusCode.Should().Be(200); - - _bookingsApiClient.Verify( - x => x.UpdateHearingParticipantsAsync(It.IsAny(), It.Is(x => x.LinkedParticipants.Any(x => x.LinkedParticipantContactEmail == linkedParticipantEmail))), Times.Once); - - _bookingsApiClient.Verify(x => x.UpdateHearingDetailsAsync(It.IsAny(), - It.Is(u => u.Cases.Count > 0)), Times.Once); - } - - [TestCase(BookingStatus.Booked, 0)] - [TestCase(BookingStatus.Created, 1)] - public async Task - Should_correctly_decide_when_to_send_judge_hearing_confirm_email_on_edit_when_email_has_been_updated( - BookingStatus status, int timeSent) - { - // arrange - var hearingId = _updatedExistingParticipantHearingOriginal.Id; - var newJudgeEmailOtherInfo = new OtherInformationDetails { JudgeEmail = "judgene@domain.net" }; - var updatedHearing = _updatedExistingParticipantHearingOriginal.Duplicate(); - updatedHearing.Participants.Add(new ParticipantResponse - { - Id = Guid.NewGuid(), - UserRoleName = "Judge" - }); - updatedHearing.CaseTypeName = "Unit Test"; - updatedHearing.Cases[0].Name = "Case"; - updatedHearing.Cases[0].Number = "123"; - updatedHearing.OtherInformation = newJudgeEmailOtherInfo.ToOtherInformationString(); - updatedHearing.Status = status; - - _bookingsApiClient.SetupSequence(x => x.GetHearingDetailsByIdAsync(hearingId)) - .ReturnsAsync(_updatedExistingParticipantHearingOriginal) - .ReturnsAsync(updatedHearing) - .ReturnsAsync(updatedHearing); - - _bookingsApiClient.Setup(x => x.GetHearingsByGroupIdAsync(updatedHearing.GroupId.Value)) - .ReturnsAsync(new List { updatedHearing }); - var request = new EditHearingRequest - { - Case = new EditCaseRequest { Name = "Case", Number = "123" }, - OtherInformation = updatedHearing.OtherInformation - }; - - // act - var result = await _controller.EditHearing(hearingId, request); - - // assert - ((OkObjectResult)result.Result).StatusCode.Should().Be(200); - } - - [Test] - public async Task Should_handle_failed_booking_request_on_retry() - { - _existingHearingWithJudge.ScheduledDateTime = DateTime.UtcNow.AddMinutes(10); - _existingHearingWithJudge.Status = BookingStatus.Failed; - _bookingsApiClient.SetupSequence(x => x.GetHearingDetailsByIdAsync(It.IsAny())) - .ReturnsAsync(_existingHearingWithJudge) - .ReturnsAsync(_existingHearingWithJudge); - - var request = FailedHearingRequest(); - - var result = await _controller.EditHearing(_validId, request); - - var response = ((ObjectResult)result.Result)?.Value as AdminWebsite.Contracts.Responses.HearingDetailsResponse; - - response.Status.Should().Be((AdminWebsite.Contracts.Enums.BookingStatus)BookingStatus.Failed); - - ((ObjectResult)result.Result).StatusCode.Should().Be(200); - - _bookingsApiClient.Verify(x => x.UpdateHearingParticipantsAsync( - It.IsAny(), - It.IsAny()), - Times.Once); - } - - private EditHearingRequest FailedHearingRequest() - { - return new EditHearingRequest - { - Case = new EditCaseRequest - { - Name = "Case", - Number = "123" - }, - Participants = new List - { - new EditParticipantRequest - { - ContactEmail = "test@domain.net.", - FirstName = "FirstName", - LastName = "LastName", - HearingRoleName = HearingRoleName.Judge - } - } - }; - } - } } \ No newline at end of file diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditMultiDayHearingTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditMultiDayHearingTests.cs index 9f0d758da..4e7d1e789 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditMultiDayHearingTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditMultiDayHearingTests.cs @@ -794,55 +794,7 @@ public async Task Should_return_bad_request_when_hearing_is_not_multi_day() } private static readonly string[] value = ["Please provide a valid id"]; - - [Test] - public async Task Should_forward_bad_request_from_bookings_api() - { - // Arrange - var hearingId = Guid.NewGuid(); - var request = new EditMultiDayHearingRequest(); - var validationProblemDetails = new ValidationProblemDetails(new Dictionary - { - {"id", value } - }); - var apiException = new BookingsApiException("BadRequest", - (int)HttpStatusCode.BadRequest, - "Please provide a valid id", - null, - validationProblemDetails, - null); - BookingsApiClient.Setup(x => x.GetHearingDetailsByIdAsync(hearingId)) - .ThrowsAsync(apiException); - - // Act - var result = await Controller.EditMultiDayHearing(hearingId, request); - - var objectResult = (ObjectResult)result.Result; - var validationProblems = (ValidationProblemDetails)objectResult.Value; - - var errors = validationProblems.Errors; - errors.Should().BeEquivalentTo(validationProblemDetails.Errors); - } - [Test] - public void Should_forward_unhandled_error_from_bookings_api() - { - // Arrange - var hearingId = Guid.NewGuid(); - var request = new EditMultiDayHearingRequest(); - var errorMessage = "Unexpected error for unit test"; - var apiException = new BookingsApiException("Server Error", - (int) HttpStatusCode.InternalServerError, - "Server Error", null, errorMessage, null); - BookingsApiClient.Setup(x => x.GetHearingDetailsByIdAsync(hearingId)) - .ThrowsAsync(apiException); - - // Act & Assert - var response = Controller.EditMultiDayHearing(hearingId, request); - - ((ObjectResult)response.Result.Result).StatusCode.Should().Be(500); - } - private static HearingDetailsResponseV2 MapUpdatedHearingV2( HearingDetailsResponseV2 hearing, EditMultiDayHearingRequest request) => new() diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetHearingTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetHearingTests.cs index 9761a414a..94b440c4d 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetHearingTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetHearingTests.cs @@ -265,27 +265,5 @@ public async Task Should_return_ok_status_for_cancelled_multi_day_hearing() response.MultiDayHearingLastDayScheduledDateTime.Should().BeNull(); response.HearingsInGroup.Should().BeEquivalentTo(multiDayHearings.Select(x => x.Map())); } - - [Test] - public async Task Should_return_bad_request_if_hearing_id_is_empty() - { - // Arrange - GivenApiThrowsExceptionOnGetHearing(HttpStatusCode.BadRequest); - - var invalidId = Guid.Empty; - - // Act - var result = await _controller.GetHearingById(invalidId); - - // Assert - var badRequestResult = (BadRequestObjectResult) result; - badRequestResult.StatusCode.Should().Be(400); - } - - private void GivenApiThrowsExceptionOnGetHearing(HttpStatusCode code) - { - _mocker.Mock().Setup(x => x.GetHearingDetailsByIdAsync(It.IsAny())) - .ThrowsAsync(ClientException.ForBookingsAPI(code)); - } } } diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetStatusHearingTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetStatusHearingTests.cs index 78f8ab92c..5ed9dc922 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetStatusHearingTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetStatusHearingTests.cs @@ -106,76 +106,6 @@ public void Initialise() .ReturnsAsync(GetHearingDetailsResponseV2(BookingsApi.Contract.V2.Enums.BookingStatusV2.Booked)); } - [Test] - public async Task Should_return_ok_true_status_when_booking_status_is_created_and_has_valid_room() - { - ConferenceDetailsResponse conferenceResponse = new() { MeetingRoom = new() { - AdminUri = "AdminUri", ParticipantUri = "ParticipantUri", JudgeUri = "JudgeUri", PexipNode = "PexipNode"} }; - - // Arrange - _conferenceDetailsServiceMock.Setup(x => x.GetConferenceDetailsByHearingId(_guid, false)) - .ReturnsAsync(conferenceResponse); - _vhExistingHearing.Status = BookingStatus.Created; - - // Act - var result = await _controller.GetHearingConferenceStatus(_guid); - - // Assert - var okRequestResult = (OkObjectResult)result; - okRequestResult.StatusCode.Should().Be(200); - - var hearing = (UpdateBookingStatusResponse)((OkObjectResult)result).Value; - hearing.Success.Should().Be(true); - _conferenceDetailsServiceMock.Verify(x => x.GetConferenceDetailsByHearingId(It.IsAny(), false), Times.Once); - _bookingsApiClientMock.Verify(x => x.GetHearingDetailsByIdAsync(It.IsAny()), Times.Once); - } - - [Test] - public async Task Should_return_ok_with_false_when_hearing_status_is_created_and_invalid_room() - { - ConferenceDetailsResponse conferenceResponse = new() { MeetingRoom = new MeetingRoomResponse() }; - - // Arrange - _conferenceDetailsServiceMock.Setup(x => x.GetConferenceDetailsByHearingId(It.IsAny(), false)) - .ReturnsAsync(conferenceResponse); - _vhExistingHearing.Status = BookingStatus.Created; - - // Act - var result = await _controller.GetHearingConferenceStatus(_guid); - - // Assert - var okRequestResult = (OkObjectResult)result; - okRequestResult.StatusCode.Should().Be(200); - - var hearing = (UpdateBookingStatusResponse)((OkObjectResult)result).Value; - hearing.Success.Should().Be(false); - _conferenceDetailsServiceMock.Verify(x => x.GetConferenceDetailsByHearingId(It.IsAny(), false), Times.Once); - _bookingsApiClientMock.Verify(x => x.GetHearingDetailsByIdAsync(It.IsAny()), Times.Once); - } - - [Test] - public async Task Should_return_ok_status_if_hearing_has_not_valid_room_and_status_is_booked() - { - ConferenceDetailsResponse conferenceResponse = new() { MeetingRoom = new MeetingRoomResponse() }; - - // Arrange - _conferenceDetailsServiceMock.Setup(x => x.GetConferenceDetailsByHearingId(It.IsAny(), false)) - .ReturnsAsync(conferenceResponse); - _bookingsApiClientMock.Setup(x => x.GetBookingStatusByIdAsync(It.IsAny())).ReturnsAsync(BookingStatus.Booked); - - // Act - var result = await _controller.GetHearingConferenceStatus(_guid); - - // Assert - var okRequestResult = (OkObjectResult)result; - okRequestResult.StatusCode.Should().Be(200); - - var hearing = (UpdateBookingStatusResponse)((OkObjectResult)result).Value; - hearing.Success.Should().Be(false); - _conferenceDetailsServiceMock.Verify(x => x.GetConferenceDetailsByHearingId(It.IsAny(), false), Times.Never); - _bookingsApiClientMock.Verify(x => x.GetHearingDetailsByIdAsync(It.IsAny()), Times.Once); - } - [Test] public async Task Should_return_false_when_hearing_not_be_found() { @@ -190,44 +120,7 @@ public async Task Should_return_false_when_hearing_not_be_found() notFoundResult.StatusCode.Should().Be(200); ((UpdateBookingStatusResponse)notFoundResult.Value)?.Success.Should().BeFalse(); } - - [Test] - public async Task Should_return_BadRequest_when_issue_with_finding_hearing_with_bookings_api() - { - - ConferenceDetailsResponse conferenceResponse = new ConferenceDetailsResponse(); - conferenceResponse.MeetingRoom = new MeetingRoomResponse(); - - - // Arrange - _bookingsApiClientMock.Setup(x => x.GetHearingDetailsByIdAsync(It.IsAny())).Throws(new BookingsApiException("Error", 400, null, null, null)); - // Act - var result = await _controller.GetHearingConferenceStatus(_guid); - - // Assert - var badRequest = (BadRequestObjectResult)result; - badRequest.StatusCode.Should().Be(400); - } - - [Test] - public async Task Should_return_BadRequest_when_issue_with_finding_hearing_with_video_api() - { - - ConferenceDetailsResponse conferenceResponse = new ConferenceDetailsResponse(); - conferenceResponse.MeetingRoom = new MeetingRoomResponse(); - - - // Arrange - _vhExistingHearing.Status = BookingStatus.Created; - _conferenceDetailsServiceMock.Setup(x => x.GetConferenceDetailsByHearingId(It.IsAny(), false)).Throws(new VideoApiException("Error", 400, null, null, null)); - // Act - var result = await _controller.GetHearingConferenceStatus(_guid); - - // Assert - var badRequest = (BadRequestObjectResult)result; - badRequest.StatusCode.Should().Be(400); - } - + [Test] public async Task Should_return_not_found_if_hearing_failed_to_be_found() { diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/PostHearingTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/PostHearingTests.cs index ef1c743fc..4a6d32ceb 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/PostHearingTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/PostHearingTests.cs @@ -56,143 +56,6 @@ public void Setup() }); _controller = _mocker.Create(); } - - [Test] - public async Task Should_create_a_hearing_with_endpoints() - { - - var newHearingRequest = new BookingDetailsRequest - { - Participants = new List - { - new () - { - CaseRoleName = "CaseRole", - ContactEmail = "contact1@hmcts.net", - HearingRoleName = "HearingRole", - DisplayName = "display name1", - FirstName = "fname", - MiddleNames = "", - LastName = "lname1", - Username = "username1@hmcts.net", - OrganisationName = "", - Representee = "", - TelephoneNumber = "" - }, - new () - { - CaseRoleName = "CaseRole", ContactEmail = "contact2@hmcts.net", - HearingRoleName = "HearingRole", DisplayName = "display name2", - FirstName = "fname2", MiddleNames = "", LastName = "lname2", - Username = "username2@hmcts.net", OrganisationName = "", Representee = "", - TelephoneNumber = "" - }, - }, - Endpoints = new List - { - new () {DisplayName = "displayname1", DefenceAdvocateContactEmail = "username1@hmcts.net"}, - new () {DisplayName = "displayname2", DefenceAdvocateContactEmail = "username2@hmcts.net"}, - } - }; - - var bookingRequest = new BookHearingRequest - { - BookingDetails = newHearingRequest - }; - - // setup response - var hearingDetailsResponse = HearingResponseBuilder.Build() - .WithEndPoints(2) - .WithParticipant("Representative", "username1@hmcts.net") - .WithParticipant("Individual", "username2@hmcts.net"); - _mocker.Mock().Setup(x => x.BookNewHearingAsync(It.IsAny())) - .ReturnsAsync(hearingDetailsResponse); - _mocker.Mock().Setup(x => x.GetAdUserIdForUsername(It.IsAny())).ReturnsAsync(Guid.NewGuid().ToString()); - - var result = await _controller.Post(bookingRequest); - - result.Result.Should().BeOfType(); - var createdObjectResult = (CreatedResult)result.Result; - createdObjectResult.StatusCode.Should().Be(201); - } - - [Test] - public async Task Should_create_a_hearing_with_LinkedParticipants() - { - // request. - var newHearingRequest = new BookingDetailsRequest() - { - Participants = new List - { - new () { CaseRoleName = "CaseRole", ContactEmail = "firstName1.lastName1@email.com", - DisplayName = "firstName1 lastName1", FirstName = "firstName1", HearingRoleName = "Litigant in person", LastName = "lastName1", MiddleNames = "", - OrganisationName = "", Representee = "", TelephoneNumber = "1234567890", Title = "Mr.", Username = "firstName1.lastName1@email.net" }, - new () { CaseRoleName = "CaseRole", ContactEmail = "firstName2.lastName2@email.com", - DisplayName = "firstName2 lastName2", FirstName = "firstName2", HearingRoleName = "Interpreter", LastName = "lastName2", MiddleNames = "", - OrganisationName = "", Representee = "", TelephoneNumber = "1234567890", Title = "Mr.", Username = "firstName2.lastName2@email.net" }, - - }, - LinkedParticipants = new List - { - new () { ParticipantContactEmail = "firstName1.lastName1@email.com", LinkedParticipantContactEmail = "firstName2.lastName2@email.com", Type = LinkedParticipantType.Interpreter }, - new () { ParticipantContactEmail = "firstName2.lastName2@email.com", LinkedParticipantContactEmail = "firstName1.lastName1@email.com", Type = LinkedParticipantType.Interpreter } - } - }; - - var bookingRequest = new BookHearingRequest - { - BookingDetails = newHearingRequest - }; - // set response. - var linkedParticipant1 = new List { new () { LinkedId = Guid.NewGuid(), Type = V1.Enums.LinkedParticipantType.Interpreter } }; - var participant1 = Builder.CreateNew().With(x => x.Id = Guid.NewGuid()) - .With(x => x.UserRoleName = "Individual").With(x => x.Username = "firstName1.lastName1@email.net") - .With(x => x.LinkedParticipants = linkedParticipant1) - .Build(); - var linkedParticipant2 = new List() { new () { LinkedId = Guid.NewGuid(), Type = V1.Enums.LinkedParticipantType.Interpreter } }; - var participant2 = Builder.CreateNew().With(x => x.Id = Guid.NewGuid()) - .With(x => x.UserRoleName = "Individual").With(x => x.Username = "firstName1.lastName1@email.net") - .With(x => x.LinkedParticipants = linkedParticipant2) - .Build(); - var hearingDetailsResponse = Builder.CreateNew() - .With(x => x.Cases = Builder.CreateListOfSize(2).Build().ToList()) - .With(x => x.Endpoints = Builder.CreateListOfSize(2).Build().ToList()) - .With(x => x.Participants = new List { participant1, participant2 }).Build(); - _mocker.Mock().Setup(x => x.BookNewHearingAsync(It.IsAny())) - .ReturnsAsync(hearingDetailsResponse); - _mocker.Mock().Setup(x => x.GetAdUserIdForUsername(It.IsAny())).ReturnsAsync(Guid.NewGuid().ToString()); - - var result = await _controller.Post(bookingRequest); - result.Result.Should().BeOfType(); - var createdObjectResult = (CreatedResult)result.Result; - createdObjectResult.StatusCode.Should().Be(201); - } - - [Test] - public async Task Should_pass_bad_request_from_bookings_api() - { - var hearing = new BookingDetailsRequest() - { - Participants = new List() - }; - - var bookingRequest = new BookHearingRequest - { - BookingDetails = hearing - }; - - const string key = "ScheduledDateTime"; - const string errorMessage = "ScheduledDateTime cannot be in the past"; - var validationProblemDetails = new ValidationProblemDetails(new Dictionary - { - {key, [errorMessage] }, - }); - _mocker.Mock().Setup(x => x.BookNewHearingAsync(It.IsAny())) - .Throws(ClientException.ForBookingsAPIValidation(validationProblemDetails)); - - var result = await _controller.Post(bookingRequest); - result.Result.Should().BeOfType(); - } [Test] public void Should_throw_BookingsApiException() @@ -235,31 +98,7 @@ public void Should_throw_Exception() ((ObjectResult) response.Result.Result).StatusCode.Should().Be(500); } - - [Test] - public async Task Should_pass_current_user_as_created_by_to_service() - { - const string CURRENT_USERNAME = "test@hmcts.net"; - _mocker.Mock().Setup(x => x.GetUserIdentityName()).Returns(CURRENT_USERNAME); - - // setup response - var hearingDetailsResponse = HearingResponseBuilder.Build() - .WithParticipant("Representative") - .WithParticipant("Individual"); - _mocker.Mock().Setup(x => x.BookNewHearingAsync(It.IsAny())) - .ReturnsAsync(hearingDetailsResponse); - - var result = await PostNewHearing(); - - result.Result.Should().BeOfType(); - var createdResult = (CreatedResult)result.Result; - createdResult.Location.Should().Be(""); - - _mocker.Mock().Verify(x => x.BookNewHearingAsync(It.Is( - request => request.CreatedBy == CURRENT_USERNAME)), Times.Once); - _mocker.Mock().Verify(x => x.AssignParticipantToGroup(It.IsAny(), It.IsAny()), Times.Never); - } - + [Test] public async Task Should_clone_hearing() { diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/ReferenceDataControllerTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/ReferenceDataControllerTests.cs index 70381c958..d15b0dc6f 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/ReferenceDataControllerTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/ReferenceDataControllerTests.cs @@ -69,7 +69,7 @@ public async Task Should_return_participants_roles() { List listTypes; listTypes = new List { new CaseRoleResponseV2 { Name = "type1" } }; - SetTestCase(listTypes, true); + SetTestCase(listTypes); var response = await _controller.GetParticipantRoles("type1"); response.Should().NotBeNull(); @@ -108,27 +108,17 @@ public async Task Should_return_empty_list_of_participants_roles_if_list_types_i caseRoles.Count.Should().Be(0); } - private void SetTestCase(List listTypes, bool refDataToggle = false) + private void SetTestCase(List listTypes) { - var listHearingRoles = new List { new HearingRoleResponse { Name = "type1", UserRole = "role1"} }; var listHearingRoles2 = new List { new HearingRoleResponseV2 { Name = "type1", UserRole = "role1"} }; _userIdentityMock.Setup(x => x.GetAdministratorCaseTypes()).Returns(new List { "type1", "type2" }); - if (refDataToggle) - { - //v2 endpoints - var casetypeV2Response = listTypes?.Select(e => (CaseRoleResponseV2)e).ToList(); - _bookingsApiClientMock.Setup(x => x.GetCaseRolesForCaseServiceAsync(It.IsAny())).ReturnsAsync(casetypeV2Response); - _bookingsApiClientMock.Setup(x => x.GetHearingRolesForCaseRoleV2Async(It.IsAny(), It.IsAny())).ReturnsAsync(listHearingRoles2); - } - else - { - //V1 endpoints - var casetypeV1Response = listTypes?.Select(e => (CaseRoleResponse)e).ToList(); - _bookingsApiClientMock.Setup(x => x.GetCaseRolesForCaseTypeAsync(It.IsAny())).ReturnsAsync(casetypeV1Response); - _bookingsApiClientMock.Setup(x => x.GetHearingRolesForCaseRoleAsync(It.IsAny(), It.IsAny())).ReturnsAsync(listHearingRoles); - - } + + //v2 endpoints + var casetypeV2Response = listTypes?.Select(e => (CaseRoleResponseV2)e).ToList(); + _bookingsApiClientMock.Setup(x => x.GetCaseRolesForCaseServiceAsync(It.IsAny())).ReturnsAsync(casetypeV2Response); + _bookingsApiClientMock.Setup(x => x.GetHearingRolesForCaseRoleV2Async(It.IsAny(), It.IsAny())).ReturnsAsync(listHearingRoles2); + } private static List GetCaseTypesList() diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.ts index 62e1b58ca..df70236b9 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.ts @@ -6,7 +6,6 @@ import { first, map } from 'rxjs/operators'; export const FeatureFlags = { dom1Integration: 'dom1', - referenceData: 'reference-data', multiDayBookingEnhancements: 'multi-day-booking-enhancements' }; diff --git a/AdminWebsite/AdminWebsite/Configuration/FeatureToggles.cs b/AdminWebsite/AdminWebsite/Configuration/FeatureToggles.cs index 79e3b7c28..670c4f039 100644 --- a/AdminWebsite/AdminWebsite/Configuration/FeatureToggles.cs +++ b/AdminWebsite/AdminWebsite/Configuration/FeatureToggles.cs @@ -9,7 +9,6 @@ namespace AdminWebsite.Configuration public interface IFeatureToggles { public bool Dom1Enabled(); - public bool ReferenceDataToggle(); } public class FeatureToggles : IFeatureToggles @@ -18,7 +17,6 @@ public class FeatureToggles : IFeatureToggles private readonly Context _context; private const string LdUser = "vh-admin-web"; private const string Dom1EnabledToggleKey = "dom1"; - private const string ReferenceDataToggleKey = "reference-data"; public FeatureToggles(string sdkKey, string environmentName) @@ -34,11 +32,6 @@ public bool Dom1Enabled() return GetBoolValueWithKey(Dom1EnabledToggleKey); } - public bool ReferenceDataToggle() - { - return GetBoolValueWithKey(ReferenceDataToggleKey); - } - private bool GetBoolValueWithKey(string key) { if (!_ldClient.Initialized) diff --git a/AdminWebsite/AdminWebsite/Controllers/ReferenceDataController.cs b/AdminWebsite/AdminWebsite/Controllers/ReferenceDataController.cs index 1377e89dc..406f7d898 100644 --- a/AdminWebsite/AdminWebsite/Controllers/ReferenceDataController.cs +++ b/AdminWebsite/AdminWebsite/Controllers/ReferenceDataController.cs @@ -81,16 +81,9 @@ public async Task>> GetParticipa { var response = new List(); List iCaseRoles; - if (_featureToggles.ReferenceDataToggle()) - { - var caseRoles2 = await _bookingsApiClient.GetCaseRolesForCaseServiceAsync(caseTypeParameter); - iCaseRoles = caseRoles2?.Select(e => (ICaseRoleResponse)e).ToList(); - } - else - { - var caseRoles1 = await _bookingsApiClient.GetCaseRolesForCaseTypeAsync(caseTypeParameter); - iCaseRoles = caseRoles1?.Select(e => (ICaseRoleResponse)e).ToList(); - } + var caseRoles2 = await _bookingsApiClient.GetCaseRolesForCaseServiceAsync(caseTypeParameter); + iCaseRoles = caseRoles2?.Select(e => (ICaseRoleResponse)e).ToList(); + if (iCaseRoles != null && iCaseRoles.Any()) { @@ -98,16 +91,8 @@ public async Task>> GetParticipa { var caseRole = new CaseAndHearingRolesResponse { Name = caseRoleName }; List iHearingRoles; - if (_featureToggles.ReferenceDataToggle()) - { - var hearingRoles1 = await _bookingsApiClient.GetHearingRolesForCaseRoleV2Async(caseTypeParameter, caseRoleName); - iHearingRoles = hearingRoles1.Select(e => (IHearingRoleResponse)e).ToList(); - } - else - { - var hearingRoles2 = await _bookingsApiClient.GetHearingRolesForCaseRoleAsync(caseTypeParameter, caseRoleName); - iHearingRoles = hearingRoles2.Select(e => (IHearingRoleResponse)e).ToList(); - } + var hearingRoles1 = await _bookingsApiClient.GetHearingRolesForCaseRoleV2Async(caseTypeParameter, caseRoleName); + iHearingRoles = hearingRoles1.Select(e => (IHearingRoleResponse)e).ToList(); caseRole.HearingRoles = iHearingRoles.ConvertAll(x => new HearingRole(x.Name, x.UserRole)); From 32afa451b1a75a98042f56a93a928cffdeaca3cc Mon Sep 17 00:00:00 2001 From: marcogagliardi Date: Mon, 10 Jun 2024 15:36:11 +0100 Subject: [PATCH 08/25] test fixed --- .../HearingsController/EditHearingTests.cs | 5 +- .../GetStatusHearingTests.cs | 3 +- .../HearingsControllerTests.cs | 5 +- .../assign-judge/assign-judge.component.ts | 1 - .../bookings-list.component.spec.ts | 98 ++++++++++++++++++- .../Controllers/AudioPlatformController.cs | 4 +- .../Controllers/HearingsController.cs | 6 +- .../Controllers/ReferenceDataController.cs | 6 +- .../AdminWebsite/Services/HearingsService.cs | 5 +- 9 files changed, 105 insertions(+), 28 deletions(-) diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditHearingTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditHearingTests.cs index 54cc0de8c..aaec43083 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditHearingTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/EditHearingTests.cs @@ -85,14 +85,13 @@ public void Setup() _kinlyOptionsMock.Setup((op) => op.Value).Returns(_kinlyConfigurationMock.Object); _participantGroupLogger = new Mock>(); - _hearingsService = new HearingsService(_bookingsApiClient.Object, _participantGroupLogger.Object, _featureToggle.Object); + _hearingsService = new HearingsService(_bookingsApiClient.Object, _participantGroupLogger.Object); _controller = new AdminWebsite.Controllers.HearingsController(_bookingsApiClient.Object, _userIdentity.Object, _editHearingRequestValidator.Object, new Mock>().Object, _hearingsService, - _conferencesServiceMock.Object, - _featureToggle.Object); + _conferencesServiceMock.Object); _validId = Guid.NewGuid(); _addNewParticipantRequest = new EditHearingRequest diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetStatusHearingTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetStatusHearingTests.cs index 5ed9dc922..d3eeaf20d 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetStatusHearingTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/GetStatusHearingTests.cs @@ -44,8 +44,7 @@ public void Setup() new Mock>().Object, new Mock>().Object, _hearingServiceMock.Object, - _conferenceDetailsServiceMock.Object, - _featureFlag.Object); + _conferenceDetailsServiceMock.Object); Initialise(); diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/HearingsControllerTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/HearingsControllerTests.cs index 7a6cfae7a..e9357e5e0 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/HearingsControllerTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/HearingsController/HearingsControllerTests.cs @@ -60,15 +60,14 @@ protected virtual void Setup() _kinlyOptionsMock.Setup((op) => op.Value).Returns(_kinlyConfigurationMock.Object); _participantGroupLogger = new Mock>(); - _hearingsService = new HearingsService(BookingsApiClient.Object, _participantGroupLogger.Object, FeatureToggle.Object); + _hearingsService = new HearingsService(BookingsApiClient.Object, _participantGroupLogger.Object); Controller = new AdminWebsite.Controllers.HearingsController(BookingsApiClient.Object, UserIdentity.Object, _editHearingRequestValidator.Object, new Mock>().Object, _hearingsService, - _conferencesServiceMock.Object, - FeatureToggle.Object); + _conferencesServiceMock.Object); } protected static List CreateListOfV1HearingsInMultiDayGroup( diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/assign-judge/assign-judge.component.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/assign-judge/assign-judge.component.ts index fccc5d836..0088ddaed 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/assign-judge/assign-judge.component.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/assign-judge/assign-judge.component.ts @@ -349,7 +349,6 @@ export class AssignJudgeComponent extends BookingBaseComponent implements OnInit if (!this.isExistingJudge(judge)) { if (this.hearingService.canAddJudge(judge.username)) { judge.is_judge = true; - judge.case_role_name = 'Judge'; judge.case_role_name = null; judge.hearing_role_code = Constants.HearingRoleCodes.Judge; judge.hearing_role_name = 'Judge'; diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.spec.ts index 98f96ccbe..c0bc2def4 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.spec.ts @@ -590,8 +590,6 @@ describe('BookingsListComponent', () => { videoHearingServiceSpy.getHearingTypes.and.returnValue(of(new Array())); configServiceSpy.getConfig.and.returnValue({}); - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.useV2Api).and.returnValue(of(false)); - referenceDataServiceSpy.getCourts.and.returnValue(of(new Array())); featureFlagServiceSpy.getFeatureFlagByName.and.returnValue(of(false)); @@ -662,6 +660,102 @@ describe('BookingsListComponent', () => { expect(component.loaded).toBeTruthy(); }); + it('should onSearch', () => { + bookingsListServiceSpy.getBookingsList.calls.reset(); + setFormValue(); + component.onSearch(); + expect(bookingPersistService.caseNumber).toMatch('CASE_NUMBER'); + expect(bookingPersistService.participantLastName).toMatch('PARTICIPANT_LAST_NAME'); + expect(bookingPersistService.startDate).toEqual(moment().startOf('day').add(1, 'days').toDate()); + expect(bookingPersistService.endDate).toEqual(moment().startOf('day').add(2, 'days').toDate()); + expect(component.bookings.length).toBeGreaterThan(0); + expect(bookingsListServiceSpy.getBookingsList).toHaveBeenCalledWith( + undefined, + component.limit, + bookingPersistService.caseNumber, + bookingPersistService.selectedVenueIds, + bookingPersistService.selectedCaseTypes, + bookingPersistService.selectedUsers, + moment(bookingPersistService.startDate).startOf('day').toDate(), + moment(bookingPersistService.endDate).endOf('day').toDate(), + bookingPersistService.participantLastName, + bookingPersistService.noJugdeInHearings, + bookingPersistService.noAllocatedHearings + ); + + it('should onSearch with populated endDate and empty startDate', () => { + bookingsListServiceSpy.getBookingsList.calls.reset(); + setFormValue(); + component.searchForm.controls['startDate'].setValue(null); + component.onSearch(); + expect(bookingPersistService.caseNumber).toMatch('CASE_NUMBER'); + expect(bookingPersistService.participantLastName).toMatch('PARTICIPANT_LAST_NAME'); + expect(bookingPersistService.startDate).toBeNull(); + expect(bookingPersistService.endDate).toEqual(moment().startOf('day').add(2, 'days').toDate()); + expect(component.bookings.length).toBeGreaterThan(0); + expect(bookingsListServiceSpy.getBookingsList).toHaveBeenCalledWith( + undefined, + component.limit, + bookingPersistService.caseNumber, + bookingPersistService.selectedVenueIds, + bookingPersistService.selectedCaseTypes, + bookingPersistService.selectedUsers, + moment(bookingPersistService.endDate).startOf('day').toDate(), + moment(bookingPersistService.endDate).endOf('day').toDate(), + bookingPersistService.participantLastName, + bookingPersistService.noJugdeInHearings, + bookingPersistService.noAllocatedHearings + ); + }); + + it('should onSearch with populated startDate and empty endDate', () => { + bookingsListServiceSpy.getBookingsList.calls.reset(); + setFormValue(); + + component.searchForm.controls['endDate'].setValue(null); + component.onSearch(); + expect(bookingPersistService.caseNumber).toMatch('CASE_NUMBER'); + expect(bookingPersistService.participantLastName).toMatch('PARTICIPANT_LAST_NAME'); + expect(bookingPersistService.startDate).toEqual(moment().startOf('day').add(1, 'days').toDate()); + expect(bookingPersistService.endDate).toBeNull(); + expect(component.bookings.length).toBeGreaterThan(0); + expect(bookingsListServiceSpy.getBookingsList).toHaveBeenCalledWith( + undefined, + component.limit, + bookingPersistService.caseNumber, + bookingPersistService.selectedVenueIds, + bookingPersistService.selectedCaseTypes, + bookingPersistService.selectedUsers, + moment(bookingPersistService.startDate).startOf('day').toDate(), + moment(bookingPersistService.startDate).endOf('day').toDate(), + bookingPersistService.participantLastName, + bookingPersistService.noJugdeInHearings, + bookingPersistService.noAllocatedHearings + ); + }); + + it('should onSearch with no judge option selected', () => { + bookingsListServiceSpy.getBookingsList.calls.reset(); + setFormValue(true); + component.searchForm.controls['endDate'].setValue(null); + component.onSearch(); + expect(bookingPersistService.noJugdeInHearings).toBeTruthy(); + expect(bookingsListServiceSpy.getBookingsList).toHaveBeenCalledWith( + undefined, + component.limit, + bookingPersistService.caseNumber, + bookingPersistService.selectedVenueIds, + bookingPersistService.selectedCaseTypes, + bookingPersistService.selectedUsers, + moment(bookingPersistService.startDate).startOf('day').toDate(), + moment(bookingPersistService.startDate).endOf('day').toDate(), + bookingPersistService.participantLastName, + bookingPersistService.noJugdeInHearings, + bookingPersistService.noAllocatedHearings + ); + }); + }); + describe('noJudgeInHearing', () => { it('no judge option is ON', () => { const optionSelected = true; diff --git a/AdminWebsite/AdminWebsite/Controllers/AudioPlatformController.cs b/AdminWebsite/AdminWebsite/Controllers/AudioPlatformController.cs index 400803d4a..17e9d4dc6 100644 --- a/AdminWebsite/AdminWebsite/Controllers/AudioPlatformController.cs +++ b/AdminWebsite/AdminWebsite/Controllers/AudioPlatformController.cs @@ -24,14 +24,12 @@ public class AudioPlatformController : ControllerBase private readonly IVideoApiClient _videoAPiClient; private readonly IBookingsApiClient _bookingsApiClient; private readonly ILogger _logger; - private readonly IFeatureToggles _featureToggles; - public AudioPlatformController(IVideoApiClient videoAPiClient, ILogger logger, IBookingsApiClient bookingsApiClient, IFeatureToggles featureToggles) + public AudioPlatformController(IVideoApiClient videoAPiClient, ILogger logger, IBookingsApiClient bookingsApiClient) { _videoAPiClient = videoAPiClient; _logger = logger; _bookingsApiClient = bookingsApiClient; - _featureToggles = featureToggles; } /// diff --git a/AdminWebsite/AdminWebsite/Controllers/HearingsController.cs b/AdminWebsite/AdminWebsite/Controllers/HearingsController.cs index 2f54650a9..f3e3e1343 100644 --- a/AdminWebsite/AdminWebsite/Controllers/HearingsController.cs +++ b/AdminWebsite/AdminWebsite/Controllers/HearingsController.cs @@ -4,7 +4,6 @@ using System.Net; using System.Threading.Tasks; using AdminWebsite.Attributes; -using AdminWebsite.Configuration; using AdminWebsite.Contracts.Enums; using AdminWebsite.Contracts.Requests; using AdminWebsite.Contracts.Responses; @@ -48,7 +47,6 @@ public class HearingsController : ControllerBase private readonly IValidator _editHearingRequestValidator; private readonly IHearingsService _hearingsService; private readonly IConferenceDetailsService _conferenceDetailsService; - private readonly IFeatureToggles _featureToggles; private readonly ILogger _logger; private readonly IUserIdentity _userIdentity; @@ -61,8 +59,7 @@ public HearingsController(IBookingsApiClient bookingsApiClient, IValidator editHearingRequestValidator, ILogger logger, IHearingsService hearingsService, - IConferenceDetailsService conferenceDetailsService, - IFeatureToggles featureToggles) + IConferenceDetailsService conferenceDetailsService) { _bookingsApiClient = bookingsApiClient; _userIdentity = userIdentity; @@ -70,7 +67,6 @@ public HearingsController(IBookingsApiClient bookingsApiClient, _logger = logger; _hearingsService = hearingsService; _conferenceDetailsService = conferenceDetailsService; - _featureToggles = featureToggles; } #pragma warning restore S107 /// diff --git a/AdminWebsite/AdminWebsite/Controllers/ReferenceDataController.cs b/AdminWebsite/AdminWebsite/Controllers/ReferenceDataController.cs index 406f7d898..b559bc31f 100644 --- a/AdminWebsite/AdminWebsite/Controllers/ReferenceDataController.cs +++ b/AdminWebsite/AdminWebsite/Controllers/ReferenceDataController.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Net; using System.Threading.Tasks; -using AdminWebsite.Configuration; using AdminWebsite.Contracts.Responses; using AdminWebsite.Mappers; using AdminWebsite.Services; @@ -25,19 +24,16 @@ public class ReferenceDataController : ControllerBase { private readonly IBookingsApiClient _bookingsApiClient; private readonly IPublicHolidayRetriever _publicHolidayRetriever; - private readonly IFeatureToggles _featureToggles; /// /// Instantiate the controller /// public ReferenceDataController( IBookingsApiClient bookingsApiClient, - IPublicHolidayRetriever publicHolidayRetriever, - IFeatureToggles featureToggles) + IPublicHolidayRetriever publicHolidayRetriever) { _bookingsApiClient = bookingsApiClient; _publicHolidayRetriever = publicHolidayRetriever; - _featureToggles = featureToggles; } /// diff --git a/AdminWebsite/AdminWebsite/Services/HearingsService.cs b/AdminWebsite/AdminWebsite/Services/HearingsService.cs index 52c16ca0b..8882f84e0 100644 --- a/AdminWebsite/AdminWebsite/Services/HearingsService.cs +++ b/AdminWebsite/AdminWebsite/Services/HearingsService.cs @@ -7,7 +7,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AdminWebsite.Configuration; using AdminWebsite.Contracts.Responses; using AdminWebsite.Models.EditMultiDayHearing; using BookingsApi.Contract.Interfaces.Requests; @@ -29,14 +28,12 @@ public interface IHearingsService public class HearingsService : IHearingsService { private readonly IBookingsApiClient _bookingsApiClient; - private readonly IFeatureToggles _featureToggles; private readonly ILogger _logger; #pragma warning disable S107 - public HearingsService(IBookingsApiClient bookingsApiClient, ILogger logger, IFeatureToggles featureToggles) + public HearingsService(IBookingsApiClient bookingsApiClient, ILogger logger) { _bookingsApiClient = bookingsApiClient; _logger = logger; - _featureToggles = featureToggles; } public void AssignEndpointDefenceAdvocates(List endpointsWithDa, IReadOnlyCollection participants) From 42bc53c270b81c8393d6a02eeef4002b046223f3 Mon Sep 17 00:00:00 2001 From: marcogagliardi Date: Tue, 11 Jun 2024 08:54:24 +0100 Subject: [PATCH 09/25] Update AudioPlatformControllerTests.cs --- .../Controllers/AudioPlatformControllerTests.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/AudioPlatformControllerTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/AudioPlatformControllerTests.cs index 92c5ff25b..07c7c0267 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/AudioPlatformControllerTests.cs +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/AudioPlatformControllerTests.cs @@ -1,5 +1,4 @@ using System.Threading.Tasks; -using AdminWebsite.Configuration; using AdminWebsite.Controllers; using AdminWebsite.Models; using BookingsApi.Client; @@ -20,16 +19,14 @@ public class AudioPlatformControllerTests private readonly Mock _bookingsApiClientMock; private readonly Mock> _loggerMock; - private readonly Mock _featureTogglesMock; public AudioPlatformControllerTests() { _videoApiClientMock = new Mock(); _bookingsApiClientMock = new Mock(); _loggerMock = new Mock>(); - _featureTogglesMock = new Mock(); - _controller = new AudioPlatformController(_videoApiClientMock.Object, _loggerMock.Object, _bookingsApiClientMock.Object, _featureTogglesMock.Object); + _controller = new AudioPlatformController(_videoApiClientMock.Object, _loggerMock.Object, _bookingsApiClientMock.Object); } [Test] From a62e1756a3b82d5211177be95e1ee2668c95cd7e Mon Sep 17 00:00:00 2001 From: marcogagliardi Date: Wed, 12 Jun 2024 10:46:16 +0100 Subject: [PATCH 10/25] test fix --- .../ReferenceDataControllerTests.cs | 174 ----- .../add-participant.component.html | 20 +- .../add-participant.component.spec.ts | 650 +++++++----------- .../breadcrumb/breadcrumb.component.spec.ts | 21 +- .../breadcrumb/breadcrumb.component.ts | 3 +- .../create-hearing.component.spec.ts | 36 +- .../create-hearing.component.ts | 26 +- .../hearing-schedule.component.spec.ts | 3 - .../hearing-schedule.component.ts | 12 +- .../other-information.component.spec.ts | 1 - .../item/participant-item.component.html | 2 +- .../item/participant-item.component.spec.ts | 7 +- .../item/participant-item.component.ts | 8 +- .../booking/summary/summary.component.spec.ts | 10 - .../app/booking/summary/summary.component.ts | 21 +- .../booking-details.component.html | 2 +- .../booking-details.component.spec.ts | 14 - .../booking-details.component.ts | 9 +- .../bookings-list.component.html | 8 +- .../bookings-list.component.spec.ts | 144 ++-- .../bookings-list/bookings-list.component.ts | 12 - .../last-minute-amendments.guard.spec.ts | 39 -- .../guards/last-minute-amendments.guard.ts | 12 +- .../services/launch-darkly.service.spec.ts | 14 - .../Controllers/ReferenceDataController.cs | 129 ---- 25 files changed, 357 insertions(+), 1020 deletions(-) delete mode 100644 AdminWebsite/AdminWebsite.UnitTests/Controllers/ReferenceDataControllerTests.cs delete mode 100644 AdminWebsite/AdminWebsite/Controllers/ReferenceDataController.cs diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/ReferenceDataControllerTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/ReferenceDataControllerTests.cs deleted file mode 100644 index d15b0dc6f..000000000 --- a/AdminWebsite/AdminWebsite.UnitTests/Controllers/ReferenceDataControllerTests.cs +++ /dev/null @@ -1,174 +0,0 @@ -using System.Linq; -using System.Threading.Tasks; -using AdminWebsite.Configuration; -using Autofac.Extras.Moq; -using FizzWare.NBuilder; -using Microsoft.AspNetCore.Mvc; -using AdminWebsite.Controllers; -using AdminWebsite.Models; -using AdminWebsite.Security; -using BookingsApi.Client; -using BookingsApi.Contract.Interfaces.Response; -using BookingsApi.Contract.V1.Responses; -using BookingsApi.Contract.V2.Responses; -using HearingTypeResponse = BookingsApi.Contract.V1.Responses.HearingTypeResponse; - -namespace AdminWebsite.UnitTests.Controllers -{ - public class ReferenceDataControllerTests - { - private Mock _bookingsApiClientMock; - private Mock _userIdentityMock; - private Mock _featureTogglesMock; - private ReferenceDataController _controller; - private AutoMock _mocker; - - [SetUp] - public void Setup() - { - _mocker = AutoMock.GetLoose(); - _bookingsApiClientMock = _mocker.Mock(); - _userIdentityMock = _mocker.Mock(); - _featureTogglesMock = _mocker.Mock(); - _controller = _mocker.Create(); - } - - [Test] - public void Should_return_a_list_of_venues() - { - var hearingVenues = Builder.CreateListOfSize(2).Build().ToList(); - _bookingsApiClientMock.Setup(x => x.GetHearingVenuesAsync(true)).ReturnsAsync(hearingVenues); - - var response = _controller.GetCourts(); - var result = (OkObjectResult)response.Result.Result; - result.Value.Should().Be(hearingVenues); - } - - [Test] - public async Task Should_return_all_hearing_types_and_case_types_where_hearing_type_is_empty() - { - // Arrange - var includeDeleted = true; - _userIdentityMock.Setup(x => x.IsATeamLead()) - .Returns(true); - _bookingsApiClientMock.Setup(x => - x.GetCaseTypesAsync(includeDeleted)) - .ReturnsAsync(GetCaseTypesList()); - - // Act - var result = await _controller.GetHearingTypes(includeDeleted); - - // Assert - var okObjectResult = result.Result.Should().BeAssignableTo().Which; - okObjectResult.Value.Should().BeEquivalentTo(GetHearingTypes()); - _bookingsApiClientMock.Verify(x => x.GetCaseTypesAsync(includeDeleted), Times.Once); - } - - [Test] - public async Task Should_return_participants_roles() - { - List listTypes; - listTypes = new List { new CaseRoleResponseV2 { Name = "type1" } }; - SetTestCase(listTypes); - - var response = await _controller.GetParticipantRoles("type1"); - response.Should().NotBeNull(); - var result = (OkObjectResult)response.Result; - var caseRoles = (List)result.Value; - caseRoles[0].Name.Should().Be("type1"); - caseRoles[0].HearingRoles.Should().NotBeNull(); - caseRoles[0].HearingRoles.Count().Should().Be(1); - caseRoles[0].HearingRoles.First().Name.Should().Be("type1"); - caseRoles[0].HearingRoles.First().UserRole.Should().Be("role1"); - } - - [Test] - public async Task Should_return_empty_list_of_participants_roles() - { - var listTypes = new List(); - SetTestCase(listTypes); - - var response = await _controller.GetParticipantRoles("type1"); - response.Should().NotBeNull(); - var result = (OkObjectResult)response.Result; - List caseRoles = (List)result.Value; - caseRoles.Count.Should().Be(0); - } - - [Test] - public async Task Should_return_empty_list_of_participants_roles_if_list_types_is_null() - { - List listTypes = null; - SetTestCase(listTypes); - - var response = await _controller.GetParticipantRoles("type1"); - response.Should().NotBeNull(); - var result = (OkObjectResult)response.Result; - List caseRoles = (List)result.Value; - caseRoles.Count.Should().Be(0); - } - - private void SetTestCase(List listTypes) - { - var listHearingRoles2 = new List { new HearingRoleResponseV2 { Name = "type1", UserRole = "role1"} }; - - _userIdentityMock.Setup(x => x.GetAdministratorCaseTypes()).Returns(new List { "type1", "type2" }); - - //v2 endpoints - var casetypeV2Response = listTypes?.Select(e => (CaseRoleResponseV2)e).ToList(); - _bookingsApiClientMock.Setup(x => x.GetCaseRolesForCaseServiceAsync(It.IsAny())).ReturnsAsync(casetypeV2Response); - _bookingsApiClientMock.Setup(x => x.GetHearingRolesForCaseRoleV2Async(It.IsAny(), It.IsAny())).ReturnsAsync(listHearingRoles2); - - } - - private static List GetCaseTypesList() - { - return new List - { - new () - { - Id = 1, Name = "type1", ServiceId = "AA1", - HearingTypes = new List() - { - new () {Id = 10, Name = "HType10", Code = "Code10"}, - } - }, - new() - { - Id = 2, Name = "type2", ServiceId = "AA2", - HearingTypes = new List() - { - new () {Id = 20, Name = "HType20", Code = "Code20"}, - } - }, - new() - { - Id = 3, Name = "type3", ServiceId = "AA3", - HearingTypes = new List() - { - new () {Id = 25, Name = "HType25", Code = "Code25"}, - new () {Id = 29, Name = "HType29", Code = "Code29"}, - } - }, - new() - { - Id = 4, Name = "type4", ServiceId = "AA4", - HearingTypes = new List() - } - }; - } - - private static List GetHearingTypes() - { - var result = new List() - { - new () {Id = 10, Name = "HType10", Group = "type1", ServiceId = "AA1", Code = "Code10"}, - new () {Id = 20, Name = "HType20", Group = "type2", ServiceId = "AA2", Code = "Code20"}, - new () {Id = 25, Name = "HType25", Group = "type3", ServiceId = "AA3", Code = "Code25"}, - new () {Id = 29, Name = "HType29", Group = "type3", ServiceId = "AA3", Code = "Code29"}, - new () {Group = "type4", ServiceId = "AA4"}, - }; - return result; - } - } -} diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/add-participant/add-participant.component.html b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/add-participant/add-participant.component.html index f5e9f7048..ae048fde7 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/add-participant/add-participant.component.html +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/add-participant/add-participant.component.html @@ -36,24 +36,6 @@

There is a probl

Add a participant

-
- - - {{ constants.Error.PartyErrorMsg }} - - - - -
-
@@ -77,7 +59,7 @@

Add a participant

> -
+
-
+
{{ title }}

-
+
Allocated to: {{ detail.AllocatedTo }}
diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.spec.ts index c0bc2def4..43f3cbe25 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.spec.ts @@ -682,78 +682,77 @@ describe('BookingsListComponent', () => { bookingPersistService.noJugdeInHearings, bookingPersistService.noAllocatedHearings ); + }); - it('should onSearch with populated endDate and empty startDate', () => { - bookingsListServiceSpy.getBookingsList.calls.reset(); - setFormValue(); - component.searchForm.controls['startDate'].setValue(null); - component.onSearch(); - expect(bookingPersistService.caseNumber).toMatch('CASE_NUMBER'); - expect(bookingPersistService.participantLastName).toMatch('PARTICIPANT_LAST_NAME'); - expect(bookingPersistService.startDate).toBeNull(); - expect(bookingPersistService.endDate).toEqual(moment().startOf('day').add(2, 'days').toDate()); - expect(component.bookings.length).toBeGreaterThan(0); - expect(bookingsListServiceSpy.getBookingsList).toHaveBeenCalledWith( - undefined, - component.limit, - bookingPersistService.caseNumber, - bookingPersistService.selectedVenueIds, - bookingPersistService.selectedCaseTypes, - bookingPersistService.selectedUsers, - moment(bookingPersistService.endDate).startOf('day').toDate(), - moment(bookingPersistService.endDate).endOf('day').toDate(), - bookingPersistService.participantLastName, - bookingPersistService.noJugdeInHearings, - bookingPersistService.noAllocatedHearings - ); - }); - - it('should onSearch with populated startDate and empty endDate', () => { - bookingsListServiceSpy.getBookingsList.calls.reset(); - setFormValue(); + it('should onSearch (admin_search flag on) with populated endDate and empty startDate', () => { + bookingsListServiceSpy.getBookingsList.calls.reset(); + setFormValue(); + component.searchForm.controls['startDate'].setValue(null); + component.onSearch(); + expect(bookingPersistService.caseNumber).toMatch('CASE_NUMBER'); + expect(bookingPersistService.participantLastName).toMatch('PARTICIPANT_LAST_NAME'); + expect(bookingPersistService.startDate).toBeNull(); + expect(bookingPersistService.endDate).toEqual(moment().startOf('day').add(2, 'days').toDate()); + expect(component.bookings.length).toBeGreaterThan(0); + expect(bookingsListServiceSpy.getBookingsList).toHaveBeenCalledWith( + undefined, + component.limit, + bookingPersistService.caseNumber, + bookingPersistService.selectedVenueIds, + bookingPersistService.selectedCaseTypes, + bookingPersistService.selectedUsers, + moment(bookingPersistService.endDate).startOf('day').toDate(), + moment(bookingPersistService.endDate).endOf('day').toDate(), + bookingPersistService.participantLastName, + bookingPersistService.noJugdeInHearings, + bookingPersistService.noAllocatedHearings + ); + }); - component.searchForm.controls['endDate'].setValue(null); - component.onSearch(); - expect(bookingPersistService.caseNumber).toMatch('CASE_NUMBER'); - expect(bookingPersistService.participantLastName).toMatch('PARTICIPANT_LAST_NAME'); - expect(bookingPersistService.startDate).toEqual(moment().startOf('day').add(1, 'days').toDate()); - expect(bookingPersistService.endDate).toBeNull(); - expect(component.bookings.length).toBeGreaterThan(0); - expect(bookingsListServiceSpy.getBookingsList).toHaveBeenCalledWith( - undefined, - component.limit, - bookingPersistService.caseNumber, - bookingPersistService.selectedVenueIds, - bookingPersistService.selectedCaseTypes, - bookingPersistService.selectedUsers, - moment(bookingPersistService.startDate).startOf('day').toDate(), - moment(bookingPersistService.startDate).endOf('day').toDate(), - bookingPersistService.participantLastName, - bookingPersistService.noJugdeInHearings, - bookingPersistService.noAllocatedHearings - ); - }); + it('should onSearch (admin_search flag on) with populated startDate and empty endDate', () => { + bookingsListServiceSpy.getBookingsList.calls.reset(); + setFormValue(); + component.searchForm.controls['endDate'].setValue(null); + component.onSearch(); + expect(bookingPersistService.caseNumber).toMatch('CASE_NUMBER'); + expect(bookingPersistService.participantLastName).toMatch('PARTICIPANT_LAST_NAME'); + expect(bookingPersistService.startDate).toEqual(moment().startOf('day').add(1, 'days').toDate()); + expect(bookingPersistService.endDate).toBeNull(); + expect(component.bookings.length).toBeGreaterThan(0); + expect(bookingsListServiceSpy.getBookingsList).toHaveBeenCalledWith( + undefined, + component.limit, + bookingPersistService.caseNumber, + bookingPersistService.selectedVenueIds, + bookingPersistService.selectedCaseTypes, + bookingPersistService.selectedUsers, + moment(bookingPersistService.startDate).startOf('day').toDate(), + moment(bookingPersistService.startDate).endOf('day').toDate(), + bookingPersistService.participantLastName, + bookingPersistService.noJugdeInHearings, + bookingPersistService.noAllocatedHearings + ); + }); - it('should onSearch with no judge option selected', () => { - bookingsListServiceSpy.getBookingsList.calls.reset(); - setFormValue(true); - component.searchForm.controls['endDate'].setValue(null); - component.onSearch(); - expect(bookingPersistService.noJugdeInHearings).toBeTruthy(); - expect(bookingsListServiceSpy.getBookingsList).toHaveBeenCalledWith( - undefined, - component.limit, - bookingPersistService.caseNumber, - bookingPersistService.selectedVenueIds, - bookingPersistService.selectedCaseTypes, - bookingPersistService.selectedUsers, - moment(bookingPersistService.startDate).startOf('day').toDate(), - moment(bookingPersistService.startDate).endOf('day').toDate(), - bookingPersistService.participantLastName, - bookingPersistService.noJugdeInHearings, - bookingPersistService.noAllocatedHearings - ); - }); + it('should onSearch (admin_search flag on) with no judge option selected', () => { + bookingsListServiceSpy.getBookingsList.calls.reset(); + setFormValue(true); + component.searchForm.controls['endDate'].setValue(null); + component.onSearch(); + expect(bookingPersistService.noJugdeInHearings).toBeTruthy(); + expect(bookingsListServiceSpy.getBookingsList).toHaveBeenCalledWith( + undefined, + component.limit, + bookingPersistService.caseNumber, + bookingPersistService.selectedVenueIds, + bookingPersistService.selectedCaseTypes, + bookingPersistService.selectedUsers, + moment(bookingPersistService.startDate).startOf('day').toDate(), + moment(bookingPersistService.startDate).endOf('day').toDate(), + bookingPersistService.participantLastName, + bookingPersistService.noJugdeInHearings, + bookingPersistService.noAllocatedHearings + ); }); describe('noJudgeInHearing', () => { @@ -1015,6 +1014,12 @@ describe('BookingsListComponent', () => { expect(component.showSearch).toBe(false); }); + it('should hide the search panel on initial load', () => { + component.ngOnInit(); + fixture.detectChanges(); + expect(component.showSearch).toBe(false); + }); + it('should add bookings list records on the next scroll and delete duplicated hearings', waitForAsync(() => { component.bookings = new ArrayBookingslistModelTestData().getTestData(); component.ngOnInit(); @@ -1207,5 +1212,6 @@ describe('BookingsListComponent', () => { component.onChangeNoAllocated(); expect(bookingPersistService.selectedUsers.length).toEqual(count); }); + }); }); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.ts index 02054d981..add414a13 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.ts @@ -10,7 +10,6 @@ import { BookingsListService } from '../../services/bookings-list.service'; import { BookingPersistService } from '../../services/bookings-persist.service'; import { BookingsResponse, JusticeUserResponse } from '../../services/clients/api-client'; import { VideoHearingsService } from '../../services/video-hearings.service'; -import { FeatureFlags, LaunchDarklyService } from '../../services/launch-darkly.service'; import { PageUrls } from '../../shared/page-url.constants'; import * as moment from 'moment'; import { ReturnUrlService } from 'src/app/services/return-url.service'; @@ -46,7 +45,6 @@ export class BookingsListComponent implements OnInit, OnDestroy { selectedUserIds: []; showSearch = false; today = new Date(); - isV2 = false; destroyed$ = new Subject(); @@ -60,7 +58,6 @@ export class BookingsListComponent implements OnInit, OnDestroy { private bookingPersistService: BookingPersistService, private videoHearingService: VideoHearingsService, private formBuilder: FormBuilder, - private lanchDarklyService: LaunchDarklyService, private router: Router, private logger: Logger, private datePipe: DatePipe, @@ -68,7 +65,6 @@ export class BookingsListComponent implements OnInit, OnDestroy { ) {} ngOnInit() { - this.subscribeToFeatureFlags(); this.searchForm = this.initializeForm(); this.showSearch = this.bookingPersistService.showSearch; this.logger.debug(`${this.loggerPrefix} Loading bookings list component`); @@ -475,12 +471,4 @@ export class BookingsListComponent implements OnInit, OnDestroy { this.bookingPersistService.selectedVenueIds = $event; } - subscribeToFeatureFlags() { - this.lanchDarklyService - .getFlag(FeatureFlags.useV2Api) - .pipe(takeUntil(this.destroyed$)) - .subscribe(flag => { - this.isV2 = flag; - }); - } } diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/last-minute-amendments.guard.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/last-minute-amendments.guard.spec.ts index 8528c5074..e293490d3 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/last-minute-amendments.guard.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/last-minute-amendments.guard.spec.ts @@ -2,9 +2,7 @@ import { TestBed } from '@angular/core/testing'; import { ActivatedRouteSnapshot, Data, Router, RouterStateSnapshot, UrlSegment } from '@angular/router'; import { LastMinuteAmendmentsGuard } from './last-minute-amendments.guard'; import { VideoHearingsService } from '../../services/video-hearings.service'; -import { of } from 'rxjs'; import { Logger } from '../../services/logger'; -import { FeatureFlags, LaunchDarklyService } from '../../services/launch-darkly.service'; describe('LastMinuteAmendmentsGuard', () => { let guard: LastMinuteAmendmentsGuard; @@ -15,8 +13,6 @@ describe('LastMinuteAmendmentsGuard', () => { const loggerSpy = jasmine.createSpyObj('Logger', ['warn', 'debug']); const videoHearingsServiceSpy = jasmine.createSpyObj(['isConferenceClosed', 'isHearingAboutToStart']); const redirectPath = '/summary'; - const launchDarklyServiceSpy = jasmine.createSpyObj('LaunchDarklyService', ['getFlag']); - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.useV2Api).and.returnValue(of(true)); beforeEach(() => { TestBed.configureTestingModule({ @@ -24,7 +20,6 @@ describe('LastMinuteAmendmentsGuard', () => { LastMinuteAmendmentsGuard, { provide: VideoHearingsService, useValue: videoHearingsServiceSpy }, { provide: Router, useValue: router }, - { provide: LaunchDarklyService, useValue: launchDarklyServiceSpy }, { provide: Logger, useValue: loggerSpy } ] }).compileComponents(); @@ -64,38 +59,4 @@ describe('LastMinuteAmendmentsGuard', () => { }); }); - describe('when accessing assign-judge; last minute', () => { - it('ejudFeature flag off should override last-minute-amendment-guard and block assign-judge url to be reach', () => { - // setup - guard.isV2 = false; - const url = 'assign-judge'; - const dataSnapshot = { exceptionToRuleCheck: true } as Data; - const urlSegmentArray = [{ path: url }] as UrlSegment[]; - // execute - const returned = guard.canActivate( - { url: urlSegmentArray, data: dataSnapshot }, - { url: url } - ); - // assert - expect(returned).toBe(false); - expect(router.navigate).toHaveBeenCalledWith([redirectPath]); - }); - - it('ejudFeature flag on should allow last-minute-amendment-guard and allow assign-judge url to be reached', () => { - // setup - const url = 'assign-judge'; - const dataSnapshot = { exceptionToRuleCheck: true } as Data; - const urlSegmentArray = [{ path: url }] as UrlSegment[]; - // execute - const returned = guard.canActivate( - { url: urlSegmentArray, data: dataSnapshot }, - { url: url } - ); - // assert - expect(returned).toBe(true); - }); - afterEach(() => { - guard.isV2 = true; - }); - }); }); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/last-minute-amendments.guard.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/last-minute-amendments.guard.ts index 8eac4c053..2afbdfb4d 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/last-minute-amendments.guard.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/last-minute-amendments.guard.ts @@ -2,31 +2,21 @@ import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router'; import { VideoHearingsService } from '../../services/video-hearings.service'; import { Observable } from 'rxjs'; -import { first } from 'rxjs/operators'; import { Logger } from '../../services/logger'; -import { FeatureFlags, LaunchDarklyService } from '../../services/launch-darkly.service'; @Injectable() export class LastMinuteAmendmentsGuard { - isV2: boolean; constructor( private videoHearingsService: VideoHearingsService, private router: Router, - private featureService: LaunchDarklyService, private logger: Logger ) { - this.featureService - .getFlag(FeatureFlags.useV2Api) - .pipe(first()) - .subscribe(result => { - this.isV2 = result; - }); } canActivate(route: ActivatedRouteSnapshot, _state: RouterStateSnapshot): Observable | Promise | boolean { const exceptionToRuleCheck = route.data?.exceptionToRuleCheck as boolean; if (!this.videoHearingsService.isConferenceClosed() && this.videoHearingsService.isHearingAboutToStart()) { - if (exceptionToRuleCheck && this.isV2) { + if (exceptionToRuleCheck) { return true; } this.router.navigate(['/summary']); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.spec.ts index baae26ce8..78490325e 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.spec.ts @@ -34,18 +34,4 @@ describe('LaunchDarklyService', () => { expect(ldClientSpy.close).toHaveBeenCalled(); }); - it('should return a given flag', fakeAsync(() => { - service.client = ldClientSpy; - const flagKey = FeatureFlags.useV2Api; - const keyParam = `change:${flagKey}`; - ldClientSpy.on.withArgs(keyParam, jasmine.anything()).and.returnValue(); - ldClientSpy.waitUntilReady.and.returnValue(Promise.resolve()); - ldClientSpy.variation.withArgs(flagKey, jasmine.any(Boolean)).and.returnValue(true); - - let result: boolean; - service.getFlag(flagKey).subscribe(val => (result = val)); - tick(); - - expect(result).toBe(true); - })); }); diff --git a/AdminWebsite/AdminWebsite/Controllers/ReferenceDataController.cs b/AdminWebsite/AdminWebsite/Controllers/ReferenceDataController.cs deleted file mode 100644 index b559bc31f..000000000 --- a/AdminWebsite/AdminWebsite/Controllers/ReferenceDataController.cs +++ /dev/null @@ -1,129 +0,0 @@ -using AdminWebsite.Models; -using Microsoft.AspNetCore.Mvc; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using AdminWebsite.Contracts.Responses; -using AdminWebsite.Mappers; -using AdminWebsite.Services; -using BookingsApi.Client; -using BookingsApi.Contract.V1.Responses; -using BookingsApi.Contract.Interfaces.Response; -using HearingTypeResponse = AdminWebsite.Contracts.Responses.HearingTypeResponse; - -namespace AdminWebsite.Controllers -{ - /// - /// Responsible for retrieving reference data when requesting a booking. - /// - [Produces("application/json")] - [Route("api/reference")] - [ApiController] - public class ReferenceDataController : ControllerBase - { - private readonly IBookingsApiClient _bookingsApiClient; - private readonly IPublicHolidayRetriever _publicHolidayRetriever; - - /// - /// Instantiate the controller - /// - public ReferenceDataController( - IBookingsApiClient bookingsApiClient, - IPublicHolidayRetriever publicHolidayRetriever) - { - _bookingsApiClient = bookingsApiClient; - _publicHolidayRetriever = publicHolidayRetriever; - } - - /// - /// Gets a list hearing types - /// - /// List of hearing types - [HttpGet("types", Name = "GetHearingTypes")] - [ProducesResponseType(typeof(IList), (int)HttpStatusCode.OK)] - [ProducesResponseType((int)HttpStatusCode.NotFound)] - public async Task>> GetHearingTypes([FromQuery] bool includeDeleted = false) - { - var caseTypes = await _bookingsApiClient.GetCaseTypesAsync(includeDeleted); - var result = caseTypes.SelectMany(caseType => caseType.HearingTypes - .Select(hearingType => new HearingTypeResponse - { - Group = caseType.Name, - Id = hearingType.Id, - Name = hearingType.Name, - ServiceId = caseType.ServiceId, - Code = hearingType.Code - } )).ToList(); - - result.AddRange(caseTypes.Where(ct => !ct.HearingTypes.Any()) - .Select(caseType => new HearingTypeResponse - { - Group = caseType.Name, - ServiceId = caseType.ServiceId - })); - - return Ok(result); - } - - /// - /// Get available participant roles - /// - /// List of valid participant roles - [HttpGet("participantroles", Name = "GetParticipantRoles")] - [ProducesResponseType(typeof(IList), (int)HttpStatusCode.OK)] - [ProducesResponseType((int)HttpStatusCode.NotFound)] - public async Task>> GetParticipantRoles(string caseTypeParameter) - { - var response = new List(); - List iCaseRoles; - var caseRoles2 = await _bookingsApiClient.GetCaseRolesForCaseServiceAsync(caseTypeParameter); - iCaseRoles = caseRoles2?.Select(e => (ICaseRoleResponse)e).ToList(); - - - if (iCaseRoles != null && iCaseRoles.Any()) - { - foreach (var caseRoleName in iCaseRoles.Select(cr => cr.Name)) - { - var caseRole = new CaseAndHearingRolesResponse { Name = caseRoleName }; - List iHearingRoles; - var hearingRoles1 = await _bookingsApiClient.GetHearingRolesForCaseRoleV2Async(caseTypeParameter, caseRoleName); - iHearingRoles = hearingRoles1.Select(e => (IHearingRoleResponse)e).ToList(); - - caseRole.HearingRoles = iHearingRoles.ConvertAll(x => new HearingRole(x.Name, x.UserRole)); - - response.Add(caseRole); - } - } - - return Ok(response); - } - - /// - /// Get available courts - /// - /// List of courts - [HttpGet("courts", Name = "GetCourts")] - [ProducesResponseType(typeof(IList), (int)HttpStatusCode.OK)] - [ProducesResponseType((int)HttpStatusCode.NotFound)] - public async Task>> GetCourts() - { - var response = await _bookingsApiClient.GetHearingVenuesAsync(true); - return Ok(response); - } - - /// - /// Get upcoming public holidays in England and Wales - /// - /// List upcoming public holidays - [HttpGet("public-holidays")] - [ProducesResponseType(typeof(IList), (int)HttpStatusCode.OK)] - [ProducesResponseType((int)HttpStatusCode.NotFound)] - public async Task>> PublicHolidays() - { - var holidays = await _publicHolidayRetriever.RetrieveUpcomingHolidays(); - var response = holidays.Select(PublicHolidayResponseMapper.MapFrom).ToList(); - return Ok(response); - } - } -} \ No newline at end of file From c167bc8be357202a370f760a872dbeb13b04c6b0 Mon Sep 17 00:00:00 2001 From: marcogagliardi Date: Wed, 12 Jun 2024 10:58:25 +0100 Subject: [PATCH 11/25] lint fix --- .../add-participant/add-participant.component.spec.ts | 5 +++-- .../booking/participant/item/participant-item.component.ts | 3 +-- .../src/app/booking/summary/summary.component.spec.ts | 1 - .../ClientApp/src/app/booking/summary/summary.component.ts | 1 - .../booking-details/booking-details.component.spec.ts | 1 - .../booking-details/booking-details.component.ts | 4 +--- .../bookings-list/bookings-list.component.spec.ts | 1 - .../bookings-list/bookings-list/bookings-list.component.ts | 1 - .../security/guards/last-minute-amendments.guard.spec.ts | 1 - .../app/security/guards/last-minute-amendments.guard.ts | 7 +------ .../src/app/services/launch-darkly.service.spec.ts | 1 - 11 files changed, 6 insertions(+), 20 deletions(-) diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/add-participant/add-participant.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/add-participant/add-participant.component.spec.ts index 94cb88e8d..14016ed38 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/add-participant/add-participant.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/add-participant/add-participant.component.spec.ts @@ -258,11 +258,12 @@ videoHearingsServiceSpy = jasmine.createSpyObj([ ]); let bookingServiceSpy: jasmine.SpyObj; let searchServiceSpy: jasmine.SpyObj; -let launchDarklyServiceSpy: jasmine.SpyObj; const configServiceSpy = jasmine.createSpyObj('ConfigService', ['getClientSettings']); -launchDarklyServiceSpy = jasmine.createSpyObj('LaunchDarklyService', ['getFlag']); +const launchDarklyServiceSpy: jasmine.SpyObj = jasmine.createSpyObj('LaunchDarklyService', [ + 'getFlag' +]); const loggerSpy = jasmine.createSpyObj('Logger', ['error', 'debug', 'warn']); let participantServiceSpy = jasmine.createSpyObj('ParticipantService', [ 'checkDuplication', diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/participant/item/participant-item.component.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/participant/item/participant-item.component.ts index 46efca02d..6143404c6 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/participant/item/participant-item.component.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/participant/item/participant-item.component.ts @@ -35,8 +35,7 @@ export class ParticipantItemComponent implements OnInit { private logger: Logger, private router: Router, private videoHearingsService: VideoHearingsService - ) { - } + ) {} ngOnInit(): void { this.showParticipantActions = this.router.url.includes(PageUrls.AddParticipants) || this.router.url.includes(PageUrls.Summary); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/summary/summary.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/summary/summary.component.spec.ts index e2449f98e..463b8ecc5 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/summary/summary.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/summary/summary.component.spec.ts @@ -681,7 +681,6 @@ describe('SummaryComponent with invalid request', () => { expect(component.showErrorSaving).toBeTruthy(); expect(component.showWaitSaving).toBeFalsy(); }); - }); describe('SummaryComponent with existing request', () => { diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/summary/summary.component.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/summary/summary.component.ts index 2de35472b..94aaf8163 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/summary/summary.component.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/summary/summary.component.ts @@ -89,7 +89,6 @@ export class SummaryComponent implements OnInit, OnDestroy { ) { this.attemptingCancellation = false; this.showErrorSaving = false; - } ngOnInit() { diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/booking-details/booking-details.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/booking-details/booking-details.component.spec.ts index bd2aee11d..12a6af30d 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/booking-details/booking-details.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/booking-details/booking-details.component.spec.ts @@ -641,7 +641,6 @@ CY: 54321 (ID: 7777)`); discardPeriodicTasks(); })); - it('should return false when last day of multi day hearing', fakeAsync(() => { component.ngOnInit(); tick(1000); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/booking-details/booking-details.component.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/booking-details/booking-details.component.ts index b6f0d3f8b..c2364b3d0 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/booking-details/booking-details.component.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/booking-details/booking-details.component.ts @@ -364,8 +364,6 @@ CY: ${this.conferencePhoneNumberWelsh} (ID: ${this.telephoneConferenceId})`; } isMultiDayUpdateAvailable(): boolean { - return ( - this.hearing.isMultiDay && this.multiDayBookingEnhancementsEnabled && !this.hearing.isLastDayOfMultiDayHearing - ); + return this.hearing.isMultiDay && this.multiDayBookingEnhancementsEnabled && !this.hearing.isLastDayOfMultiDayHearing; } } diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.spec.ts index 43f3cbe25..0896e610f 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.spec.ts @@ -1212,6 +1212,5 @@ describe('BookingsListComponent', () => { component.onChangeNoAllocated(); expect(bookingPersistService.selectedUsers.length).toEqual(count); }); - }); }); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.ts index add414a13..aebd7be44 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/bookings-list/bookings-list.component.ts @@ -470,5 +470,4 @@ export class BookingsListComponent implements OnInit, OnDestroy { selectedVenueEmitter($event: number[]) { this.bookingPersistService.selectedVenueIds = $event; } - } diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/last-minute-amendments.guard.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/last-minute-amendments.guard.spec.ts index e293490d3..f07b6fb43 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/last-minute-amendments.guard.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/last-minute-amendments.guard.spec.ts @@ -58,5 +58,4 @@ describe('LastMinuteAmendmentsGuard', () => { expect(router.navigate).toHaveBeenCalledTimes(1); }); }); - }); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/last-minute-amendments.guard.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/last-minute-amendments.guard.ts index 2afbdfb4d..4b2f64250 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/last-minute-amendments.guard.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/security/guards/last-minute-amendments.guard.ts @@ -6,12 +6,7 @@ import { Logger } from '../../services/logger'; @Injectable() export class LastMinuteAmendmentsGuard { - constructor( - private videoHearingsService: VideoHearingsService, - private router: Router, - private logger: Logger - ) { - } + constructor(private videoHearingsService: VideoHearingsService, private router: Router, private logger: Logger) {} canActivate(route: ActivatedRouteSnapshot, _state: RouterStateSnapshot): Observable | Promise | boolean { const exceptionToRuleCheck = route.data?.exceptionToRuleCheck as boolean; diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.spec.ts index 78490325e..408a4ed40 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/launch-darkly.service.spec.ts @@ -33,5 +33,4 @@ describe('LaunchDarklyService', () => { expect(ldClientSpy.close).toHaveBeenCalled(); }); - }); From 63b6f48337b833984758e6332b6e4985b6ff7551 Mon Sep 17 00:00:00 2001 From: marcogagliardi Date: Fri, 14 Jun 2024 11:38:35 +0100 Subject: [PATCH 12/25] test fix --- .../ReferenceDataControllerTests.cs | 172 +++++++ .../add-participant.component.spec.ts | 2 - .../assign-judge.component.spec.ts | 2 - .../booking-confirmation.component.spec.ts | 4 +- .../create-hearing.component.html | 25 - .../create-hearing.component.spec.ts | 86 ---- .../endpoints/endpoints.component.spec.ts | 453 +++++++++++------- .../hearing-schedule.component.spec.ts | 6 - .../other-information.component.spec.ts | 1 - .../booking/summary/summary.component.spec.ts | 23 +- .../app/booking/summary/summary.component.ts | 1 - .../hearing-details.component.html | 2 +- .../src/app/common/model/hearing.model.ts | 2 - .../services/video-hearings.service.spec.ts | 2 - .../app/services/video-hearings.service.ts | 7 +- .../allocate-hearings.component.ts | 9 - .../Controllers/ReferenceDataController.cs | 129 +++++ 17 files changed, 584 insertions(+), 342 deletions(-) create mode 100644 AdminWebsite/AdminWebsite.UnitTests/Controllers/ReferenceDataControllerTests.cs create mode 100644 AdminWebsite/AdminWebsite/Controllers/ReferenceDataController.cs diff --git a/AdminWebsite/AdminWebsite.UnitTests/Controllers/ReferenceDataControllerTests.cs b/AdminWebsite/AdminWebsite.UnitTests/Controllers/ReferenceDataControllerTests.cs new file mode 100644 index 000000000..b69991603 --- /dev/null +++ b/AdminWebsite/AdminWebsite.UnitTests/Controllers/ReferenceDataControllerTests.cs @@ -0,0 +1,172 @@ +using System.Linq; +using System.Threading.Tasks; +using AdminWebsite.Configuration; +using Autofac.Extras.Moq; +using FizzWare.NBuilder; +using Microsoft.AspNetCore.Mvc; +using AdminWebsite.Controllers; +using AdminWebsite.Models; +using AdminWebsite.Security; +using BookingsApi.Client; +using BookingsApi.Contract.Interfaces.Response; +using BookingsApi.Contract.V1.Responses; +using BookingsApi.Contract.V2.Responses; +using HearingTypeResponse = BookingsApi.Contract.V1.Responses.HearingTypeResponse; + +namespace AdminWebsite.UnitTests.Controllers +{ + public class ReferenceDataControllerTests + { + private Mock _bookingsApiClientMock; + private Mock _userIdentityMock; + private ReferenceDataController _controller; + private AutoMock _mocker; + + [SetUp] + public void Setup() + { + _mocker = AutoMock.GetLoose(); + _bookingsApiClientMock = _mocker.Mock(); + _userIdentityMock = _mocker.Mock(); + _controller = _mocker.Create(); + } + + [Test] + public void Should_return_a_list_of_venues() + { + var hearingVenues = Builder.CreateListOfSize(2).Build().ToList(); + _bookingsApiClientMock.Setup(x => x.GetHearingVenuesAsync(true)).ReturnsAsync(hearingVenues); + + var response = _controller.GetCourts(); + var result = (OkObjectResult)response.Result.Result; + result.Value.Should().Be(hearingVenues); + } + + [Test] + public async Task Should_return_all_hearing_types_and_case_types_where_hearing_type_is_empty() + { + // Arrange + var includeDeleted = true; + _userIdentityMock.Setup(x => x.IsATeamLead()) + .Returns(true); + _bookingsApiClientMock.Setup(x => + x.GetCaseTypesAsync(includeDeleted)) + .ReturnsAsync(GetCaseTypesList()); + + // Act + var result = await _controller.GetHearingTypes(includeDeleted); + + // Assert + var okObjectResult = result.Result.Should().BeAssignableTo().Which; + okObjectResult.Value.Should().BeEquivalentTo(GetHearingTypes()); + _bookingsApiClientMock.Verify(x => x.GetCaseTypesAsync(includeDeleted), Times.Once); + } + + [Test] + public async Task Should_return_participants_roles() + { + List listTypes; + listTypes = new List { new CaseRoleResponseV2 { Name = "type1" } }; + SetTestCase(listTypes); + + var response = await _controller.GetParticipantRoles("type1"); + response.Should().NotBeNull(); + var result = (OkObjectResult)response.Result; + var caseRoles = (List)result.Value; + caseRoles[0].Name.Should().Be("type1"); + caseRoles[0].HearingRoles.Should().NotBeNull(); + caseRoles[0].HearingRoles.Count().Should().Be(1); + caseRoles[0].HearingRoles.First().Name.Should().Be("type1"); + caseRoles[0].HearingRoles.First().UserRole.Should().Be("role1"); + } + + [Test] + public async Task Should_return_empty_list_of_participants_roles() + { + var listTypes = new List(); + SetTestCase(listTypes); + + var response = await _controller.GetParticipantRoles("type1"); + response.Should().NotBeNull(); + var result = (OkObjectResult)response.Result; + List caseRoles = (List)result.Value; + caseRoles.Count.Should().Be(0); + } + + [Test] + public async Task Should_return_empty_list_of_participants_roles_if_list_types_is_null() + { + List listTypes = null; + SetTestCase(listTypes); + + var response = await _controller.GetParticipantRoles("type1"); + response.Should().NotBeNull(); + var result = (OkObjectResult)response.Result; + List caseRoles = (List)result.Value; + caseRoles.Count.Should().Be(0); + } + + private void SetTestCase(List listTypes) + { + var listHearingRoles2 = new List { new HearingRoleResponseV2 { Name = "type1", UserRole = "role1"} }; + + _userIdentityMock.Setup(x => x.GetAdministratorCaseTypes()).Returns(new List { "type1", "type2" }); + + //v2 endpoints + var casetypeV2Response = listTypes?.Select(e => (CaseRoleResponseV2)e).ToList(); + _bookingsApiClientMock.Setup(x => x.GetCaseRolesForCaseServiceAsync(It.IsAny())).ReturnsAsync(casetypeV2Response); + _bookingsApiClientMock.Setup(x => x.GetHearingRolesForCaseRoleV2Async(It.IsAny(), It.IsAny())).ReturnsAsync(listHearingRoles2); + + } + + private static List GetCaseTypesList() + { + return new List + { + new () + { + Id = 1, Name = "type1", ServiceId = "AA1", + HearingTypes = new List() + { + new () {Id = 10, Name = "HType10", Code = "Code10"}, + } + }, + new() + { + Id = 2, Name = "type2", ServiceId = "AA2", + HearingTypes = new List() + { + new () {Id = 20, Name = "HType20", Code = "Code20"}, + } + }, + new() + { + Id = 3, Name = "type3", ServiceId = "AA3", + HearingTypes = new List() + { + new () {Id = 25, Name = "HType25", Code = "Code25"}, + new () {Id = 29, Name = "HType29", Code = "Code29"}, + } + }, + new() + { + Id = 4, Name = "type4", ServiceId = "AA4", + HearingTypes = new List() + } + }; + } + + private static List GetHearingTypes() + { + var result = new List() + { + new () {Id = 10, Name = "HType10", Group = "type1", ServiceId = "AA1", Code = "Code10"}, + new () {Id = 20, Name = "HType20", Group = "type2", ServiceId = "AA2", Code = "Code20"}, + new () {Id = 25, Name = "HType25", Group = "type3", ServiceId = "AA3", Code = "Code25"}, + new () {Id = 29, Name = "HType29", Group = "type3", ServiceId = "AA3", Code = "Code29"}, + new () {Group = "type4", ServiceId = "AA4"}, + }; + return result; + } + } +} diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/add-participant/add-participant.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/add-participant/add-participant.component.spec.ts index 14016ed38..4793679e9 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/add-participant/add-participant.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/add-participant/add-participant.component.spec.ts @@ -199,7 +199,6 @@ const constants = Constants; function initHearingRequest(): HearingModel { const newHearing = new HearingModel(); newHearing.cases = []; - newHearing.hearing_type_id = -1; newHearing.hearing_venue_id = -1; newHearing.scheduled_duration = 0; newHearing.participants = participants; @@ -212,7 +211,6 @@ function initExistHearingRequest(): HearingModel { const newHearing = new HearingModel(); newHearing.cases = []; newHearing.hearing_id = '12345'; - newHearing.hearing_type_id = 1; newHearing.hearing_venue_id = 1; newHearing.scheduled_duration = 20; newHearing.participants = participants; diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/assign-judge/assign-judge.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/assign-judge/assign-judge.component.spec.ts index c1d793fd5..9ec145eb0 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/assign-judge/assign-judge.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/assign-judge/assign-judge.component.spec.ts @@ -57,7 +57,6 @@ function initHearingRequest(): HearingModel { newHearing.cases = []; newHearing.participants = participants; - newHearing.hearing_type_id = -1; newHearing.hearing_venue_id = -1; newHearing.scheduled_date_time = null; newHearing.scheduled_duration = 0; @@ -90,7 +89,6 @@ describe('AssignJudgeComponent', () => { 'validateEmail' ]); videoHearingsServiceSpy = jasmine.createSpyObj('VideoHearingsService', [ - 'getHearingTypes', 'getCurrentRequest', 'updateHearingRequest', 'cancelRequest', diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/booking-confirmation/booking-confirmation.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/booking-confirmation/booking-confirmation.component.spec.ts index 49400af44..c0e193090 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/booking-confirmation/booking-confirmation.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/booking-confirmation/booking-confirmation.component.spec.ts @@ -6,7 +6,7 @@ import { CaseModel } from 'src/app/common/model/case.model'; import { HearingModel } from 'src/app/common/model/hearing.model'; import { ParticipantModel } from 'src/app/common/model/participant.model'; import { VideoHearingsService } from 'src/app/services/video-hearings.service'; -import { LongDatetimePipe } from '../../../app/shared/directives/date-time.pipe'; +import { LongDatetimePipe } from '../../shared/directives/date-time.pipe'; import { Logger } from '../../services/logger'; import { BookingConfirmationComponent } from './booking-confirmation.component'; import { BookingStatus, HearingDetailsResponse } from 'src/app/services/clients/api-client'; @@ -65,7 +65,6 @@ function initHearingRequest(): HearingModel { const today = new Date(); today.setHours(14, 30); - newHearing.hearing_type_id = -1; newHearing.hearing_venue_id = -1; newHearing.scheduled_date_time = today; newHearing.scheduled_duration = 0; @@ -85,7 +84,6 @@ describe('BookingConfirmationComponent', () => { loggerSpy = jasmine.createSpyObj('Logger', ['error', 'debug', 'warn']); routerSpy = jasmine.createSpyObj('Router', ['navigate']); videoHearingsServiceSpy = jasmine.createSpyObj('VideoHearingsService', [ - 'getHearingTypes', 'getCurrentRequest', 'updateHearingRequest', 'getHearingById', diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/create-hearing/create-hearing.component.html b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/create-hearing/create-hearing.component.html index dddb51233..305e7cdf8 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/create-hearing/create-hearing.component.html +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/create-hearing/create-hearing.component.html @@ -23,9 +23,6 @@

Please complete
  • Please enter a case type
  • -
  • - Please enter a hearing type -
  • @@ -90,28 +87,6 @@

    Please complete -
    - - - - - -
    - Please select a hearing type -
    -
    -
    diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/create-hearing/create-hearing.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/create-hearing/create-hearing.component.spec.ts index e94c1a333..c8794a2fe 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/create-hearing/create-hearing.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/create-hearing/create-hearing.component.spec.ts @@ -23,7 +23,6 @@ import { createMultiDayHearing } from 'src/app/testing/helpers/hearing.helpers'; function initHearingRequest(): HearingModel { const newHearing = new HearingModel(); - newHearing.hearing_type_id = -1; newHearing.hearing_venue_id = -1; newHearing.scheduled_duration = 0; return newHearing; @@ -31,7 +30,6 @@ function initHearingRequest(): HearingModel { function initExistingHearingRequest(): HearingModel { const existingRequest = new HearingModel(); - existingRequest.hearing_type_id = 2; existingRequest.hearing_venue_id = 1; existingRequest.case_type = 'Generic'; @@ -99,7 +97,6 @@ describe('CreateHearingComponent with multiple case types', () => { it('should not set case type when multiple items returned', () => { fixture.detectChanges(); expect(component).toBeTruthy(); - expect(component.availableHearingTypes.length).toBe(3); }); it('should fail validation when form is empty', () => { @@ -134,29 +131,6 @@ describe('CreateHearingComponent with multiple case types', () => { component.failedSubmission = true; expect(component.caseNumberInvalid).toBeTruthy(); }); - it('should validate case type', () => { - const caseTypeValue = 'Tax'; - expect(caseNumberControl.valid).toBeFalsy(); - caseTypeControl.setValue(caseTypeValue); - expect(component.selectedCaseType).toBe(caseTypeValue); - expect(caseTypeControl.valid).toBeTruthy(); - }); - - it('should update hearing request when form is valid', () => { - expect(component.form.valid).toBeFalsy(); - - caseNameControl.setValue('Captain America vs The World'); - caseNumberControl.setValue('12345'); - caseTypeControl.setValue('Tax'); - hearingTypeControl.setValue(2); - - expect(component.form.valid).toBeTruthy(); - component.saveHearingDetails(); - expect(component.hearing.hearing_type_id).toBe(2); - const hearingTypeName = MockValues.HearingTypesList.find(c => c.id === component.hearing.hearing_type_id).name; - expect(component.hearing.hearing_type_name).toBe(hearingTypeName); - expect(component.hearing.cases.length).toBe(1); - }); }); describe('CreateHearingComponent with single case type', () => { @@ -200,15 +174,6 @@ describe('CreateHearingComponent with single case type', () => { fixture.detectChanges(); }); - it('should set case type when single item returned', fakeAsync(() => { - videoHearingsServiceSpy.getHearingTypes.and.returnValue(of(MockValues.HearingTypesSingle)); - fixture.detectChanges(); - tick(); - fixture.detectChanges(); - expect(component.availableHearingTypes.length).toBe(1); - expect(component.selectedCaseType).toBeDefined(); - })); - it('should show cancel booking confirmation pop up', () => { component.editMode = false; component.form.markAsDirty(); @@ -218,63 +183,12 @@ describe('CreateHearingComponent with single case type', () => { }); }); -describe('CreateHearingComponent', () => { - let component: CreateHearingComponent; - let fixture: ComponentFixture; - let hearingTypeControl: AbstractControl; - const newHearing = initHearingRequest(); - - beforeEach(() => { - launchDarklyServiceSpy = jasmine.createSpyObj('LaunchDarklyService', ['getFlag']); - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.multiDayBookingEnhancements).and.returnValue(of(false)); - - videoHearingsServiceSpy = jasmine.createSpyObj('VideoHearingsService', [ - 'getHearingTypes', - 'getCurrentRequest', - 'updateHearingRequest', - 'cancelRequest', - 'setBookingHasChanged' - ]); - routerSpy = jasmine.createSpyObj('Router', ['navigate']); - bookingServiceSpy = jasmine.createSpyObj('BookingSErvice', ['isEditMode', 'resetEditMode', 'removeEditMode']); - videoHearingsServiceSpy.getCurrentRequest.and.returnValue(newHearing); - videoHearingsServiceSpy.getHearingTypes.and.returnValue(of(MockValues.HearingTypesSingle)); - - TestBed.configureTestingModule({ - imports: [HttpClientModule, ReactiveFormsModule, RouterTestingModule], - providers: [ - { provide: VideoHearingsService, useValue: videoHearingsServiceSpy }, - { provide: Router, useValue: routerSpy }, - { provide: ErrorService, useValue: errorService }, - { provide: BookingService, useValue: bookingServiceSpy }, - { provide: Logger, useValue: loggerSpy }, - { provide: LaunchDarklyService, useValue: launchDarklyServiceSpy } - ], - declarations: [CreateHearingComponent, BreadcrumbComponent, CancelPopupComponent, DiscardConfirmPopupComponent] - }).compileComponents(); - - fixture = TestBed.createComponent(CreateHearingComponent); - component = fixture.componentInstance; - component.ngOnInit(); - fixture.detectChanges(); - - hearingTypeControl = component.form.controls['hearingType']; - }); - - it('should pass validation when no hearing type is not set', () => { - expect(hearingTypeControl.valid).toBeTruthy(); - hearingTypeControl.setValue(2); - expect(hearingTypeControl.valid).toBeTruthy(); - }); -}); - describe('CreateHearingComponent with existing request in session', () => { let component: CreateHearingComponent; let fixture: ComponentFixture; let caseNameElement: HTMLInputElement; let caseNumberElement: HTMLInputElement; const existingRequest = initExistingHearingRequest(); - existingRequest.hearing_type_name = 'Automated Test'; beforeEach(() => { launchDarklyServiceSpy = jasmine.createSpyObj('LaunchDarklyService', ['getFlag']); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/endpoints/endpoints.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/endpoints/endpoints.component.spec.ts index 8973bc4f9..790bd3743 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/endpoints/endpoints.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/endpoints/endpoints.component.spec.ts @@ -1,109 +1,74 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { Router } from '@angular/router'; +import { RouterTestingModule } from '@angular/router/testing'; import { of } from 'rxjs'; -import { EndpointsComponent } from './endpoints.component'; +import { EndpointModel } from 'src/app/common/model/endpoint.model'; +import { HearingModel } from 'src/app/common/model/hearing.model'; +import { ParticipantModel } from 'src/app/common/model/participant.model'; +import { CancelPopupComponent } from 'src/app/popups/cancel-popup/cancel-popup.component'; +import { DiscardConfirmPopupComponent } from 'src/app/popups/discard-confirm-popup/discard-confirm-popup.component'; import { BookingService } from 'src/app/services/booking.service'; -import { VideoHearingsService } from 'src/app/services/video-hearings.service'; +import { ErrorService } from 'src/app/services/error.service'; import { Logger } from 'src/app/services/logger'; -import { FeatureFlags, LaunchDarklyService } from 'src/app/services/launch-darkly.service'; -import { FormBuilder, ReactiveFormsModule } from '@angular/forms'; -import { HearingModel } from '../../common/model/hearing.model'; -import { VideoEndpointFormComponent } from './video-endpoint-form/video-endpoint-form.component'; -import { VideoEndpointListComponent } from './video-endpoint-list/video-endpoint-list.component'; -import { VideoEndpointItemComponent } from './video-endpoint-item/video-endpoint-item.component'; +import { VideoHearingsService } from 'src/app/services/video-hearings.service'; +import { SharedModule } from 'src/app/shared/shared.module'; +import { MockValues } from 'src/app/testing/data/test-objects'; +import { BreadcrumbComponent } from '../breadcrumb/breadcrumb.component'; +import { EndpointsComponent } from './endpoints.component'; +import { LaunchDarklyService, FeatureFlags } from 'src/app/services/launch-darkly.service'; import { BreadcrumbStubComponent } from 'src/app/testing/stubs/breadcrumb-stub'; function initHearingRequest(): HearingModel { const newHearing = new HearingModel(); - newHearing.hearing_type_id = -1; newHearing.hearing_venue_id = -1; newHearing.scheduled_duration = 0; - newHearing.participants = [ - { - id: '1', - first_name: 'John', - last_name: 'Doe', - email: 'john@doe.com', - display_name: 'John Doe', - user_role_name: 'Representative' - }, - { - id: '2', - first_name: 'Chris', - last_name: 'Green', - email: 'chris@green,com', - display_name: 'Chris Green', - user_role_name: 'Representative' - }, - { - id: '3', - first_name: 'Jane', - last_name: 'Smith', - email: 'jane@smith.com', - display_name: 'Jane Smith', - user_role_name: 'Individual' - } - ]; - newHearing.endpoints = [ - { - id: '1', - displayName: 'Already Here', - defenceAdvocate: null, - sip: 'sip', - pin: 'pin', - username: 'test@existing.com', - contactEmail: 'test@existing.com' - } - ]; return newHearing; } +let videoHearingsServiceSpy: jasmine.SpyObj; +let launchDarklyServiceSpy: jasmine.SpyObj; +let routerSpy: jasmine.SpyObj; +const errorService: jasmine.SpyObj = jasmine.createSpyObj('ErrorService', ['handleError']); +let bookingServiceSpy: jasmine.SpyObj; + describe('EndpointsComponent', () => { let component: EndpointsComponent; let fixture: ComponentFixture; - let bookingServiceSpy: jasmine.SpyObj; - let videoHearingsServiceSpy: jasmine.SpyObj; - let routerSpy: jasmine.SpyObj; - let loggerSpy: jasmine.SpyObj; - let featureServiceSpy: jasmine.SpyObj; + const loggerSpy = jasmine.createSpyObj('Logger', ['error', 'debug', 'warn']); const newHearing = initHearingRequest(); - beforeEach(async () => { - bookingServiceSpy = jasmine.createSpyObj('BookingService', ['removeEditMode', 'isEditMode', 'resetEditMode']); - videoHearingsServiceSpy = jasmine.createSpyObj('VideoHearingsService', [ + beforeEach(waitForAsync(() => { + launchDarklyServiceSpy = jasmine.createSpyObj('LaunchDarklyService', ['getFlag']); + launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.multiDayBookingEnhancements).and.returnValue(of(false)); + + videoHearingsServiceSpy = jasmine.createSpyObj('VideoHearingsService', [ 'getCurrentRequest', - 'isHearingAboutToStart', 'updateHearingRequest', + 'setBookingHasChanged', 'cancelRequest', - 'setBookingHasChanged' + 'isHearingAboutToStart' ]); + routerSpy = jasmine.createSpyObj('Router', ['navigate']); videoHearingsServiceSpy.getCurrentRequest.and.returnValue(newHearing); + bookingServiceSpy = jasmine.createSpyObj('BookingService', ['isEditMode', 'resetEditMode', 'removeEditMode']); - routerSpy = jasmine.createSpyObj('Router', ['navigate']); - loggerSpy = jasmine.createSpyObj('Logger', ['debug']); - featureServiceSpy = jasmine.createSpyObj('LaunchDarklyService', ['getFlag']); - featureServiceSpy.getFlag.withArgs(FeatureFlags.multiDayBookingEnhancements).and.returnValue(of(false)); - - await TestBed.configureTestingModule({ - declarations: [ - EndpointsComponent, - VideoEndpointFormComponent, - VideoEndpointListComponent, - VideoEndpointItemComponent, - BreadcrumbStubComponent - ], + TestBed.configureTestingModule({ + imports: [SharedModule, RouterTestingModule], providers: [ - { provide: BookingService, useValue: bookingServiceSpy }, { provide: VideoHearingsService, useValue: videoHearingsServiceSpy }, { provide: Router, useValue: routerSpy }, + { provide: ErrorService, useValue: errorService }, + { provide: BookingService, useValue: bookingServiceSpy }, { provide: Logger, useValue: loggerSpy }, - { provide: LaunchDarklyService, useValue: featureServiceSpy }, - FormBuilder + { provide: LaunchDarklyService, useValue: launchDarklyServiceSpy }, + { provide: BreadcrumbComponent, useValue: BreadcrumbStubComponent } ], - imports: [ReactiveFormsModule] + declarations: [EndpointsComponent, CancelPopupComponent, DiscardConfirmPopupComponent, BreadcrumbStubComponent] }).compileComponents(); + })); + beforeEach(() => { fixture = TestBed.createComponent(EndpointsComponent); component = fixture.componentInstance; fixture.detectChanges(); @@ -112,19 +77,62 @@ describe('EndpointsComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); - - it('should return true for hearing about to start', () => { - component.ngOnInit(); - videoHearingsServiceSpy.isHearingAboutToStart.and.returnValue(true); - expect(component.isHearingAboutToStart).toBe(true); - }); - it('should get booking data from storage', () => { component.ngOnInit(); fixture.detectChanges(); expect(component.hearing).toBeTruthy(); }); + it('should set return a form array', () => { + component.ngOnInit(); + expect(component.endpoints).toBeTruthy(); + }); + it('should have multiple endpoints', () => { + component.ngOnInit(); + component.endpoints.controls[0].get('displayName').setValue('100'); + component.addEndpoint(); + component.endpoints.controls[1].get('displayName').setValue('200'); + component.addEndpoint(); + expect(component.hasEndpoints).toBe(true); + }); + describe('when booking is multi day', () => { + beforeEach(() => { + const booking = new HearingModel(); + booking.isMultiDay = true; + videoHearingsServiceSpy.getCurrentRequest.and.returnValue(booking); + }); + it('should navigate to the summary page when next clicked and multi day booking enhancements are enabled', () => { + launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.multiDayBookingEnhancements).and.returnValue(of(true)); + component.ngOnInit(); + component.saveEndpoints(); + expect(routerSpy.navigate).toHaveBeenCalledWith(['/summary']); + }); + it('should navigate to the other information page when next clicked and multi day booking enhancements are not enabled', () => { + launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.multiDayBookingEnhancements).and.returnValue(of(false)); + component.ngOnInit(); + component.saveEndpoints(); + expect(routerSpy.navigate).toHaveBeenCalledWith(['/other-information']); + }); + }); + describe('when booking is not multi day', () => { + beforeEach(() => { + const booking = new HearingModel(); + booking.isMultiDay = false; + videoHearingsServiceSpy.getCurrentRequest.and.returnValue(booking); + }); + it('should navigate to the other information page when next clicked and multi day booking enhancements are enabled', () => { + launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.multiDayBookingEnhancements).and.returnValue(of(true)); + component.ngOnInit(); + component.saveEndpoints(); + expect(routerSpy.navigate).toHaveBeenCalledWith(['/other-information']); + }); + it('should navigate to the other information page when next clicked and multi day booking enhancements are not enabled', () => { + launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.multiDayBookingEnhancements).and.returnValue(of(false)); + component.ngOnInit(); + component.saveEndpoints(); + expect(routerSpy.navigate).toHaveBeenCalledWith(['/other-information']); + }); + }); it('should show a confirmation popup if cancel clicked in new mode', () => { bookingServiceSpy.isEditMode.and.returnValue(false); component.ngOnInit(); @@ -172,113 +180,208 @@ describe('EndpointsComponent', () => { expect(component.attemptingDiscardChanges).toBeFalsy(); expect(routerSpy.navigate).toHaveBeenCalledWith(['/summary']); }); - - describe('when booking is multi day', () => { - beforeEach(() => { - const booking = new HearingModel(); - booking.isMultiDay = true; - videoHearingsServiceSpy.getCurrentRequest.and.returnValue(booking); - }); - it('should navigate to the summary page when next clicked and multi day booking enhancements are enabled', () => { - featureServiceSpy.getFlag.withArgs(FeatureFlags.multiDayBookingEnhancements).and.returnValue(of(true)); - component.ngOnInit(); - component.saveEndpoints(); - expect(routerSpy.navigate).toHaveBeenCalledWith(['/summary']); - }); - it('should navigate to the other information page when next clicked and multi day booking enhancements are not enabled', () => { - featureServiceSpy.getFlag.withArgs(FeatureFlags.multiDayBookingEnhancements).and.returnValue(of(false)); - component.ngOnInit(); - component.saveEndpoints(); - expect(routerSpy.navigate).toHaveBeenCalledWith(['/other-information']); - }); + it('it should validate display names on add another click and show error for duplicates', () => { + component.ngOnInit(); + component.endpoints.controls[0].get('displayName').setValue('200'); + component.addEndpoint(); + component.endpoints.controls[1].get('displayName').setValue('200'); + component.addEndpoint(); + expect(component.duplicateDa).toBe(true); + expect(component.failedValidation).toBe(true); + }); + it('it should validate display names on next click and show error for duplicates', () => { + component.ngOnInit(); + component.endpoints.controls[0].get('displayName').setValue('200'); + component.addEndpoint(); + component.endpoints.controls[1].get('displayName').setValue('200'); + component.saveEndpoints(); + expect(component.duplicateDa).toBe(true); + expect(component.failedValidation).toBe(true); + }); + it('it should validate display names on next click and navigate to other information page if validations pass', () => { + component.ngOnInit(); + component.endpoints.controls[0].get('displayName').setValue('200'); + component.addEndpoint(); + component.endpoints.controls[1].get('displayName').setValue('201'); + component.saveEndpoints(); + expect(component.duplicateDa).toBe(false); + expect(component.failedValidation).toBe(false); + expect(component.hearing.endpoints[0].displayName).toBe('200'); + expect(component.hearing.endpoints[1].displayName).toBe('201'); + expect(videoHearingsServiceSpy.updateHearingRequest).toHaveBeenCalled(); + expect(routerSpy.navigate).toHaveBeenCalledWith(['/other-information']); + }); + it('it should validate defence advocate on next click and navigate to other information page for defence adv none', () => { + component.ngOnInit(); + videoHearingsServiceSpy.isHearingAboutToStart.and.returnValue(false); + component.endpoints.controls[0].get('displayName').setValue('200'); + component.saveEndpoints(); + expect(component.duplicateDa).toBe(false); + expect(component.failedValidation).toBe(false); + expect(component.hearing.endpoints[0].displayName).toBe('200'); + expect(component.hearing.endpoints[0].defenceAdvocate).toBeNull(); + expect(videoHearingsServiceSpy.updateHearingRequest).toHaveBeenCalled(); + expect(routerSpy.navigate).toHaveBeenCalledWith(['/other-information']); }); - describe('when booking is not multi day', () => { - beforeEach(() => { - const booking = new HearingModel(); - booking.isMultiDay = false; - videoHearingsServiceSpy.getCurrentRequest.and.returnValue(booking); - }); - it('should navigate to the other information page when next clicked and multi day booking enhancements are enabled', () => { - featureServiceSpy.getFlag.withArgs(FeatureFlags.multiDayBookingEnhancements).and.returnValue(of(true)); - component.ngOnInit(); - component.videoEndpoints = [{ id: '1', displayName: 'Test', defenceAdvocate: null }]; - component.saveEndpoints(); - expect(routerSpy.navigate).toHaveBeenCalledWith(['/other-information']); - }); - it('should navigate to the other information page when next clicked and multi day booking enhancements are not enabled', () => { - featureServiceSpy.getFlag.withArgs(FeatureFlags.multiDayBookingEnhancements).and.returnValue(of(false)); - component.ngOnInit(); - component.saveEndpoints(); - expect(routerSpy.navigate).toHaveBeenCalledWith(['/other-information']); - }); + it('should return true for hearing about to start', () => { + component.ngOnInit(); + videoHearingsServiceSpy.isHearingAboutToStart.and.returnValue(true); + expect(component.isHearingAboutToStart).toBe(true); }); - describe('onEndpoitnAdded', () => { - it('should add endpoint', () => { - const endpoint = { id: '1', displayName: 'Test', defenceAdvocate: null }; - component.onEndpointAdded(endpoint); - expect(component.videoEndpoints).toContain(endpoint); - }); + it('it should validate fields on next click and navigate to other information page if validations pass', () => { + component.ngOnInit(); + videoHearingsServiceSpy.isHearingAboutToStart.and.returnValue(false); + component.endpoints.controls[0].get('displayName').setValue('200'); + component.endpoints.controls[0].get('defenceAdvocate').setValue('username@hmcts.net'); + component.addEndpoint(); + component.endpoints.controls[1].get('displayName').setValue('201'); + component.endpoints.controls[1].get('defenceAdvocate').setValue('username1@hmcts.net'); + component.saveEndpoints(); + expect(component.duplicateDa).toBe(false); + expect(component.failedValidation).toBe(false); + expect(component.hearing.endpoints[0].displayName).toBe('200'); + expect(component.hearing.endpoints[0].defenceAdvocate).toBe('username@hmcts.net'); + expect(component.hearing.endpoints[1].displayName).toBe('201'); + expect(component.hearing.endpoints[1].defenceAdvocate).toBe('username1@hmcts.net'); + expect(videoHearingsServiceSpy.updateHearingRequest).toHaveBeenCalled(); + expect(routerSpy.navigate).toHaveBeenCalledWith(['/other-information']); + }); - it('should not add an endpoint when the display name already exists', () => { - const endpoint = { id: '1', displayName: 'Test', defenceAdvocate: null }; - component.videoEndpoints = [endpoint]; - component.onEndpointAdded(endpoint); - expect(component.videoEndpoints.length).toBe(1); - }); + it('it should filter "Representative" user-types only as valid defenceAdvocates for JVM', () => { + // arrange + newHearing.participants = [ + { user_role_name: 'Representative', display_name: 'Counsel', hearing_role_name: 'Counsel', case_role_name: 'Appellant' }, + { user_role_name: 'Individual', display_name: 'Employer', hearing_role_name: 'Employer', case_role_name: 'Appellant' }, + { user_role_name: 'Representative', display_name: 'Solicitor', hearing_role_name: 'Solicitor', case_role_name: 'Appellant' }, + { user_role_name: 'Representative', display_name: 'Barrister', hearing_role_name: 'Barrister', case_role_name: 'Appellant' }, + { + user_role_name: 'Representative', + display_name: 'pro-bono representative', + hearing_role_name: 'pro-bono representative', + case_role_name: 'ELAAS' + }, + { + user_role_name: 'Representative', + display_name: 'Representative', + hearing_role_name: 'Representative', + case_role_name: 'Appellant' + }, + { user_role_name: 'Representative', display_name: 'Advocate1', hearing_role_name: 'Advocate', case_role_name: 'Appellant' }, + { + user_role_name: 'Individual', + display_name: 'Litigant in person', + hearing_role_name: 'Litigant in person', + case_role_name: 'Appellant' + }, + { user_role_name: 'Representative', display_name: 'Advocate2', hearing_role_name: 'Advocate', case_role_name: 'Respondent' } + ]; + videoHearingsServiceSpy.isHearingAboutToStart.and.returnValue(false); + videoHearingsServiceSpy.getCurrentRequest.and.returnValue(newHearing); + // act + component.ngOnInit(); + // assert + // Current implementation of populateDefenceAdvocates() inserts an empty record at position[0] + expect(component.availableDefenceAdvocates[1].displayName).toBe('Counsel'); + expect(component.availableDefenceAdvocates[2].displayName).toBe('Solicitor'); + expect(component.availableDefenceAdvocates[3].displayName).toBe('Barrister'); + expect(component.availableDefenceAdvocates[4].displayName).toBe('pro-bono representative'); + expect(component.availableDefenceAdvocates[5].displayName).toBe('Representative'); + expect(component.availableDefenceAdvocates[6].displayName).toBe('Advocate1'); + expect(component.availableDefenceAdvocates[7].displayName).toBe('Advocate2'); }); - describe('onEndpointUpdated', () => { - beforeEach(() => { - component.videoEndpoints = [ - { id: '1', displayName: 'Test', defenceAdvocate: null }, - { id: '2', displayName: 'Test2', defenceAdvocate: null } - ]; - }); + it('it should validate form array on next click and navigate to summary page in edit mode', () => { + videoHearingsServiceSpy.isHearingAboutToStart.and.returnValue(false); + bookingServiceSpy.isEditMode.and.returnValue(true); + component.ngOnInit(); + const existinghearing = new HearingModel(); + existinghearing.case_type = 'Case type'; + const eps: EndpointModel[] = []; + let ep = new EndpointModel(); + ep.displayName = 'displayname1'; + ep.defenceAdvocate = '12345'; + eps.push(ep); + ep = new EndpointModel(); + ep.displayName = 'displayname1'; + ep.defenceAdvocate = '11223'; + existinghearing.endpoints = eps; - it('should update endpoint', () => { - const endpoint = { id: '1', displayName: 'Test', defenceAdvocate: null }; - component.videoEndpoints = [endpoint]; - const updatedEndpoint = { id: '1', displayName: 'Updated', defenceAdvocate: null }; - component.onEndpointUpdated({ original: endpoint, updated: updatedEndpoint }); - expect(component.videoEndpoints).toContain(updatedEndpoint); - }); + component.hearing = existinghearing; - it('should not update endpoint when the original endpoint does not exist', () => { - const endpoint = { id: '1', displayName: 'DoesNotExist', defenceAdvocate: null }; - const updatedEndpoint = { id: '1', displayName: 'Updated', defenceAdvocate: null }; - component.onEndpointUpdated({ original: endpoint, updated: updatedEndpoint }); - expect(component.videoEndpoints).not.toContain(endpoint); - }); - }); + component.endpoints.controls[0].get('displayName').setValue('new display name'); + component.endpoints.controls[0].get('defenceAdvocate').setValue('user@hmcts.net'); + component.saveEndpoints(); + expect(component.failedValidation).toBe(false); + expect(component.hearing.endpoints[0].displayName).toBe('new display name'); + expect(component.hearing.endpoints[0].defenceAdvocate).toBe('user@hmcts.net'); + expect(videoHearingsServiceSpy.updateHearingRequest).toHaveBeenCalled(); - describe('onEndpointSelectedForDeletion', () => { - beforeEach(() => { - component.videoEndpoints = [ - { id: '1', displayName: 'Test', defenceAdvocate: null }, - { id: '2', displayName: 'Test2', defenceAdvocate: null } - ]; - }); + expect(routerSpy.navigate).toHaveBeenCalledWith(['/summary']); + }); - it('should delete endpoint', () => { - const endpoint = { id: '1', displayName: 'Test', defenceAdvocate: null }; - component.onEndpointSelectedForDeletion(endpoint); - expect(component.videoEndpoints).not.toContain(endpoint); - }); + it('it should remove an endpoint from the endpoint array on remove click', () => { + videoHearingsServiceSpy.isHearingAboutToStart.and.returnValue(false); + component.ngOnInit(); + component.endpoints.controls[0].get('displayName').setValue('200'); + component.endpoints.controls[0].get('defenceAdvocate').setValue('username@hmcts.net'); + component.addEndpoint(); + component.endpoints.controls[1].get('displayName').setValue('201'); + component.endpoints.controls[1].get('defenceAdvocate').setValue('username1@hmcts.net'); + component.addEndpoint(); + component.endpoints.controls[2].get('displayName').setValue('202'); + component.endpoints.controls[2].get('defenceAdvocate').setValue('username2@hmcts.net'); - it('should not delete endpoint when the endpoint does not exist', () => { - const endpoint = { id: '3', displayName: 'Test3', defenceAdvocate: null }; - component.onEndpointSelectedForDeletion(endpoint); - expect(component.videoEndpoints.length).toBe(2); - }); + component.removeEndpoint(1); + component.saveEndpoints(); + expect(component.hearing.endpoints.length).toBe(2); }); - describe('onEndpointSelectedForEdit', () => { - it('should set endpoint to edit', () => { - const endpoint = { id: '1', displayName: 'Test', defenceAdvocate: null }; - component.onEndpointSelectedForEdit(endpoint); - expect(component.videoEndpointToEdit).toBe(endpoint); - }); + it('it should not remove an endpoint from the endpoint array on remove click when hearing is about to start', () => { + videoHearingsServiceSpy.isHearingAboutToStart.and.returnValue(true); + component.ngOnInit(); + + for (let index = 0; index <= 2; index++) { + component.addEndpoint(); + component.endpoints.controls[index].get('displayName').setValue(`20${index}`); + component.endpoints.controls[index].get('defenceAdvocate').setValue(`username${index}@hmcts.net`); + } + + component.removeEndpoint(1); + component.saveEndpoints(); + expect(component.hearing.endpoints.length).toBe(3); + }); + it('should map participant list to defence advocate model', () => { + videoHearingsServiceSpy.isHearingAboutToStart.and.returnValue(false); + const participantModel = new ParticipantModel(); + participantModel.id = '1000'; + participantModel.email = 'username@hmcts.net'; + participantModel.display_name = 'display name'; + component.ngOnInit(); + const dA = component.mapParticipantsToDefenceAdvocateModel(participantModel); + expect(dA).toBeTruthy(); + expect(dA.id).toBe('1000'); + expect(dA.contactEmail).toBe('username@hmcts.net'); + expect(dA.displayName).toBe('display name'); + expect(dA.isSelected).toBe(null); + }); + it('should return the username from id', () => { + videoHearingsServiceSpy.isHearingAboutToStart.and.returnValue(false); + const participantModel = new ParticipantModel(); + participantModel.id = '1000'; + participantModel.email = 'username@hmcts.net'; + participantModel.display_name = 'display name'; + component.hearing.participants.push(participantModel); + component.ngOnInit(); + let result = component.getEmailFromId('1000'); + expect(result).toBe('username@hmcts.net'); + result = component.getEmailFromId('1001'); + expect(result).toBe('1001'); + }); + it('should unsubscribe all subcription on destroy', () => { + videoHearingsServiceSpy.isHearingAboutToStart.and.returnValue(false); + component.ngOnDestroy(); + expect(component.$subscriptions[0].closed).toBe(true); }); }); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/hearing-schedule/hearing-schedule.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/hearing-schedule/hearing-schedule.component.spec.ts index af6cee6ef..e99ac820d 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/hearing-schedule/hearing-schedule.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/hearing-schedule/hearing-schedule.component.spec.ts @@ -30,7 +30,6 @@ function initExistingHearingRequest(): HearingModel { today.setHours(10, 30); const existingRequest = new HearingModel(); - existingRequest.hearing_type_id = 2; existingRequest.hearing_venue_id = 1; existingRequest.scheduled_date_time = today; existingRequest.scheduled_duration = 80; @@ -85,7 +84,6 @@ describe('HearingScheduleComponent first visit', () => { referenceDataServiceServiceSpy = jasmine.createSpyObj('ReferenceDataService', ['getCourts']); referenceDataServiceServiceSpy.getCourts.and.returnValue(of(MockValues.Courts)); videoHearingsServiceSpy = jasmine.createSpyObj('VideoHearingsService', [ - 'getHearingTypes', 'getCurrentRequest', 'updateHearingRequest', 'cancelRequest', @@ -415,7 +413,6 @@ describe('HearingScheduleComponent returning to page', () => { referenceDataServiceServiceSpy = jasmine.createSpyObj('ReferenceDataService', ['getCourts']); referenceDataServiceServiceSpy.getCourts.and.returnValue(of(MockValues.Courts)); videoHearingsServiceSpy = jasmine.createSpyObj('VideoHearingsService', [ - 'getHearingTypes', 'getCurrentRequest', 'updateHearingRequest', 'cancelRequest', @@ -542,8 +539,6 @@ describe('HearingScheduleComponent returning to page', () => { referenceDataServiceServiceSpy.getCourts.and.returnValue(of(courts)); const existingHearingRequest = { ...existingRequest }; existingHearingRequest.hearing_id = '123455555900'; - existingHearingRequest.hearing_type_name = 'HearingTypeName'; - existingHearingRequest.hearing_type_code = null; existingHearingRequest.court_name = selectedCourt.name; existingHearingRequest.court_id = selectedCourt.id; videoHearingsServiceSpy.getCurrentRequest.and.returnValue(existingHearingRequest); @@ -582,7 +577,6 @@ describe('HearingScheduleComponent multi days hearing', () => { referenceDataServiceServiceSpy = jasmine.createSpyObj('ReferenceDataService', ['getCourts']); referenceDataServiceServiceSpy.getCourts.and.returnValue(of(MockValues.Courts)); videoHearingsServiceSpy = jasmine.createSpyObj('VideoHearingsService', [ - 'getHearingTypes', 'getCurrentRequest', 'updateHearingRequest', 'cancelRequest', diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/other-information/other-information.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/other-information/other-information.component.spec.ts index 82e94cfb1..ca5b0b41c 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/other-information/other-information.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/other-information/other-information.component.spec.ts @@ -29,7 +29,6 @@ function initHearingRequest(): HearingModel { const today = new Date(); today.setHours(14, 30); - newHearing.hearing_type_id = -1; newHearing.hearing_venue_id = -1; newHearing.scheduled_date_time = today; newHearing.scheduled_duration = 0; diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/summary/summary.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/summary/summary.component.spec.ts index 463b8ecc5..af64d981b 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/summary/summary.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/summary/summary.component.spec.ts @@ -10,7 +10,7 @@ import { RemoveInterpreterPopupComponent } from 'src/app/popups/remove-interpret import { SaveFailedPopupComponent } from 'src/app/popups/save-failed-popup/save-failed-popup.component'; import { PipeStringifierService } from 'src/app/services/pipe-stringifier.service'; import { BreadcrumbStubComponent } from 'src/app/testing/stubs/breadcrumb-stub'; -import { LongDatetimePipe } from '../../../app/shared/directives/date-time.pipe'; +import { LongDatetimePipe } from '../../shared/directives/date-time.pipe'; import { CaseModel } from '../../common/model/case.model'; import { HearingModel } from '../../common/model/hearing.model'; import { ParticipantModel } from '../../common/model/participant.model'; @@ -54,7 +54,6 @@ function initExistingHearingRequest(): HearingModel { newCaseRequest.number = 'TX/12345/2018'; const existingRequest = new HearingModel(); - existingRequest.hearing_type_id = 2; existingRequest.cases.push(newCaseRequest); existingRequest.hearing_venue_id = 2; existingRequest.scheduled_date_time = today; @@ -62,8 +61,6 @@ function initExistingHearingRequest(): HearingModel { existingRequest.other_information = '|OtherInformation|some notes'; existingRequest.audio_recording_required = true; existingRequest.court_room = '123W'; - const hearingTypeName = MockValues.HearingTypesList.find(c => c.id === existingRequest.hearing_type_id).name; - existingRequest.hearing_type_name = hearingTypeName; const courtString = MockValues.Courts.find(c => c.id === existingRequest.hearing_venue_id).name; existingRequest.court_name = courtString; existingRequest.isMultiDayEdit = false; @@ -89,7 +86,6 @@ function initBadHearingRequest(): HearingModel { newCaseRequest.number = 'TX/12345/2018'; const existingRequest = new HearingModel(); - existingRequest.hearing_type_id = 2; existingRequest.cases.push(newCaseRequest); existingRequest.hearing_venue_id = 2; existingRequest.scheduled_date_time = today; @@ -108,7 +104,6 @@ recordingGuardServiceSpy = jasmine.createSpyObj('Recordin ]); const videoHearingsServiceSpy: jasmine.SpyObj = jasmine.createSpyObj('VideoHearingsService', [ - 'getHearingTypes', 'getCurrentRequest', 'updateHearingRequest', 'saveHearing', @@ -138,7 +133,6 @@ describe('SummaryComponent with valid request', () => { const mockResp = new UpdateBookingStatusResponse(); mockResp.success = true; videoHearingsServiceSpy.getCurrentRequest.and.returnValue(existingRequest); - videoHearingsServiceSpy.getHearingTypes.and.returnValue(of(MockValues.HearingTypesList)); videoHearingsServiceSpy.saveHearing.and.returnValue(Promise.resolve(ResponseTestData.getHearingResponseTestData())); videoHearingsServiceSpy.cloneMultiHearings.and.callThrough(); videoHearingsServiceSpy.getStatus.and.returnValue(Promise.resolve(mockResp)); @@ -272,8 +266,6 @@ describe('SummaryComponent with valid request', () => { expect(component.otherInformation.OtherInformation).toEqual( stringifier.decode(existingRequest.other_information).OtherInformation ); - const hearingstring = MockValues.HearingTypesList.find(c => c.id === existingRequest.hearing_type_id).name; - expect(component.caseHearingType).toEqual(hearingstring); expect(component.hearingDate).toEqual(existingRequest.scheduled_date_time); const courtString = MockValues.Courts.find(c => c.id === existingRequest.hearing_venue_id); expect(component.courtRoomAddress).toEqual(`${courtString.name}, 123W`); @@ -628,7 +620,6 @@ describe('SummaryComponent with invalid request', () => { initExistingHearingRequest(); const existingRequest = initBadHearingRequest(); videoHearingsServiceSpy.getCurrentRequest.and.returnValue(existingRequest); - videoHearingsServiceSpy.getHearingTypes.and.returnValue(of(MockValues.HearingTypesList)); const validationProblem = new ValidationProblemDetails({ errors: { @@ -691,7 +682,6 @@ describe('SummaryComponent with existing request', () => { const existingRequest = initExistingHearingRequest(); existingRequest.hearing_id = '12345ty'; videoHearingsServiceSpy.getCurrentRequest.and.returnValue(existingRequest); - videoHearingsServiceSpy.getHearingTypes.and.returnValue(of(MockValues.HearingTypesList)); videoHearingsServiceSpy.updateHearing.and.returnValue(of(new HearingDetailsResponse())); videoHearingsServiceSpy.updateMultiDayHearing.and.returnValue(of(new HearingDetailsResponse())); @@ -738,15 +728,7 @@ describe('SummaryComponent with existing request', () => { fixture.detectChanges(); expect(component.isExistingBooking).toBeTruthy(); }); - it('should retrieve hearing data', () => { - component.ngOnInit(); - fixture.detectChanges(); - expect(component.caseNumber).toBe('TX/12345/2018'); - expect(component.caseName).toBe('Mr. Test User vs HMRC'); - expect(component.caseHearingType).toBe('Automated Test'); - expect(component.courtRoomAddress).toBeTruthy(); - expect(component.hearingDuration).toBe('listed for 1 hour 20 minutes'); - }); + it('should hide pop up if continue booking pressed', () => { component.continueBooking(); fixture.detectChanges(); @@ -921,7 +903,6 @@ describe('SummaryComponent with multi days request', () => { existingRequest.isMultiDayEdit = true; existingRequest.hearing_id = '12345ty'; videoHearingsServiceSpy.getCurrentRequest.and.returnValue(existingRequest); - videoHearingsServiceSpy.getHearingTypes.and.returnValue(of(MockValues.HearingTypesList)); videoHearingsServiceSpy.updateHearing.and.returnValue(of(new HearingDetailsResponse())); const participantServiceSpy = jasmine.createSpyObj('ParticipantService', ['removeParticipant']); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/summary/summary.component.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/summary/summary.component.ts index 94aaf8163..c56e281d0 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/summary/summary.component.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/summary/summary.component.ts @@ -212,7 +212,6 @@ export class SummaryComponent implements OnInit, OnDestroy { private retrieveHearingSummary() { this.caseNumber = this.hearing.cases.length > 0 ? this.hearing.cases[0].number : ''; this.caseName = this.hearing.cases.length > 0 ? this.hearing.cases[0].name : ''; - this.caseHearingType = this.hearing.hearing_type_name; this.hearingDate = this.hearing.scheduled_date_time; this.hearingDuration = `listed for ${FormatShortDuration(this.hearing.scheduled_duration)}`; this.courtRoomAddress = this.formatCourtRoom(this.hearing.court_name, this.hearing.court_room); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/hearing-details/hearing-details.component.html b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/hearing-details/hearing-details.component.html index f4337edff..e7b8c6a20 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/hearing-details/hearing-details.component.html +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/hearing-details/hearing-details.component.html @@ -48,7 +48,7 @@

    Booki
    Allocated to: diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/common/model/hearing.model.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/common/model/hearing.model.ts index 5b4454223..9eb48eb07 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/common/model/hearing.model.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/common/model/hearing.model.ts @@ -26,8 +26,6 @@ export class HearingModel { case_type?: string; case_type_service_id?: string; other_information?: string; - judge_email?: string; - judge_phone?: string; court_room?: string; hearing_venue_id?: number; case_type_id?: number; diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/video-hearings.service.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/video-hearings.service.spec.ts index 794f26b84..3057db430 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/video-hearings.service.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/video-hearings.service.spec.ts @@ -145,7 +145,6 @@ describe('Video hearing service', () => { caseModel.number = 'Number 1'; const model = new HearingModel(); model.case_type = 'Tax'; - model.hearing_type_name = 'hearing type'; model.scheduled_date_time = new Date(date); model.scheduled_duration = 30; model.court_name = 'court address'; @@ -168,7 +167,6 @@ describe('Video hearing service', () => { caseModel.number = 'Number 1'; const model = new HearingModel(); model.case_type = 'Tax'; - model.hearing_type_name = 'hearing type'; model.scheduled_date_time = new Date(date); model.scheduled_duration = 30; model.court_name = 'court address'; diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/video-hearings.service.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/video-hearings.service.ts index dcc00e6f7..d2bb4271f 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/video-hearings.service.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/video-hearings.service.ts @@ -127,8 +127,7 @@ export class VideoHearingsService { localRequest.scheduled_date_time && localRequest.scheduled_duration > 0 && localRequest.participants.length > 1 && - localRequest.hearing_venue_id > 0 && - localRequest.hearing_type_id > 0 + localRequest.hearing_venue_id > 0 ); } @@ -323,8 +322,6 @@ export class VideoHearingsService { newHearingRequest.cases = this.mapCases(newRequest); newHearingRequest.case_type_name = newRequest.case_type; newHearingRequest.case_type_service_id = newRequest.case_type_service_id; - newHearingRequest.hearing_type_name = newRequest.hearing_type_name; - newHearingRequest.hearing_type_code = newRequest.hearing_type_code; newHearingRequest.scheduled_date_time = new Date(newRequest.scheduled_date_time); newHearingRequest.scheduled_duration = newRequest.scheduled_duration; newHearingRequest.hearing_venue_name = newRequest.court_name; @@ -344,8 +341,6 @@ export class VideoHearingsService { const hearing = new HearingModel(); hearing.hearing_id = response.id; hearing.cases = this.mapCaseResponseToCaseModel(response.cases); - hearing.hearing_type_name = response.hearing_type_name; - hearing.hearing_type_code = response.hearing_type_code; hearing.case_type = response.case_type_name; hearing.scheduled_date_time = new Date(response.scheduled_date_time); hearing.scheduled_duration = response.scheduled_duration; diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/work-allocation/allocate-hearings/allocate-hearings.component.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/work-allocation/allocate-hearings/allocate-hearings.component.ts index b4998e7a2..ecee8d92b 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/work-allocation/allocate-hearings/allocate-hearings.component.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/work-allocation/allocate-hearings/allocate-hearings.component.ts @@ -103,15 +103,6 @@ export class AllocateHearingsComponent implements OnInit { ariaLabel: item.first_name })); }); - - const distinct = (value, index, array) => array.indexOf(value) === index; - this.videoHearingService.getHearingTypes(true).subscribe((data: HearingTypeResponse[]) => { - this.caseTypesSelectOptions = data - .map(item => item.group) - .filter(distinct) - .sort((a, b) => a.localeCompare(b)) - .map(group => ({ entityId: group, label: group })); - }); } searchForHearings(keepExistingMessage: boolean = false) { diff --git a/AdminWebsite/AdminWebsite/Controllers/ReferenceDataController.cs b/AdminWebsite/AdminWebsite/Controllers/ReferenceDataController.cs new file mode 100644 index 000000000..b559bc31f --- /dev/null +++ b/AdminWebsite/AdminWebsite/Controllers/ReferenceDataController.cs @@ -0,0 +1,129 @@ +using AdminWebsite.Models; +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using AdminWebsite.Contracts.Responses; +using AdminWebsite.Mappers; +using AdminWebsite.Services; +using BookingsApi.Client; +using BookingsApi.Contract.V1.Responses; +using BookingsApi.Contract.Interfaces.Response; +using HearingTypeResponse = AdminWebsite.Contracts.Responses.HearingTypeResponse; + +namespace AdminWebsite.Controllers +{ + /// + /// Responsible for retrieving reference data when requesting a booking. + /// + [Produces("application/json")] + [Route("api/reference")] + [ApiController] + public class ReferenceDataController : ControllerBase + { + private readonly IBookingsApiClient _bookingsApiClient; + private readonly IPublicHolidayRetriever _publicHolidayRetriever; + + /// + /// Instantiate the controller + /// + public ReferenceDataController( + IBookingsApiClient bookingsApiClient, + IPublicHolidayRetriever publicHolidayRetriever) + { + _bookingsApiClient = bookingsApiClient; + _publicHolidayRetriever = publicHolidayRetriever; + } + + /// + /// Gets a list hearing types + /// + /// List of hearing types + [HttpGet("types", Name = "GetHearingTypes")] + [ProducesResponseType(typeof(IList), (int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] + public async Task>> GetHearingTypes([FromQuery] bool includeDeleted = false) + { + var caseTypes = await _bookingsApiClient.GetCaseTypesAsync(includeDeleted); + var result = caseTypes.SelectMany(caseType => caseType.HearingTypes + .Select(hearingType => new HearingTypeResponse + { + Group = caseType.Name, + Id = hearingType.Id, + Name = hearingType.Name, + ServiceId = caseType.ServiceId, + Code = hearingType.Code + } )).ToList(); + + result.AddRange(caseTypes.Where(ct => !ct.HearingTypes.Any()) + .Select(caseType => new HearingTypeResponse + { + Group = caseType.Name, + ServiceId = caseType.ServiceId + })); + + return Ok(result); + } + + /// + /// Get available participant roles + /// + /// List of valid participant roles + [HttpGet("participantroles", Name = "GetParticipantRoles")] + [ProducesResponseType(typeof(IList), (int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] + public async Task>> GetParticipantRoles(string caseTypeParameter) + { + var response = new List(); + List iCaseRoles; + var caseRoles2 = await _bookingsApiClient.GetCaseRolesForCaseServiceAsync(caseTypeParameter); + iCaseRoles = caseRoles2?.Select(e => (ICaseRoleResponse)e).ToList(); + + + if (iCaseRoles != null && iCaseRoles.Any()) + { + foreach (var caseRoleName in iCaseRoles.Select(cr => cr.Name)) + { + var caseRole = new CaseAndHearingRolesResponse { Name = caseRoleName }; + List iHearingRoles; + var hearingRoles1 = await _bookingsApiClient.GetHearingRolesForCaseRoleV2Async(caseTypeParameter, caseRoleName); + iHearingRoles = hearingRoles1.Select(e => (IHearingRoleResponse)e).ToList(); + + caseRole.HearingRoles = iHearingRoles.ConvertAll(x => new HearingRole(x.Name, x.UserRole)); + + response.Add(caseRole); + } + } + + return Ok(response); + } + + /// + /// Get available courts + /// + /// List of courts + [HttpGet("courts", Name = "GetCourts")] + [ProducesResponseType(typeof(IList), (int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] + public async Task>> GetCourts() + { + var response = await _bookingsApiClient.GetHearingVenuesAsync(true); + return Ok(response); + } + + /// + /// Get upcoming public holidays in England and Wales + /// + /// List upcoming public holidays + [HttpGet("public-holidays")] + [ProducesResponseType(typeof(IList), (int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] + public async Task>> PublicHolidays() + { + var holidays = await _publicHolidayRetriever.RetrieveUpcomingHolidays(); + var response = holidays.Select(PublicHolidayResponseMapper.MapFrom).ToList(); + return Ok(response); + } + } +} \ No newline at end of file From b2c9d333909cff97048f13e512e6ee048044eb60 Mon Sep 17 00:00:00 2001 From: marcogagliardi Date: Mon, 17 Jun 2024 11:16:12 +0100 Subject: [PATCH 13/25] Update endpoints.component.spec.ts --- .../endpoints/endpoints.component.spec.ts | 453 +++++++----------- 1 file changed, 175 insertions(+), 278 deletions(-) diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/endpoints/endpoints.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/endpoints/endpoints.component.spec.ts index 790bd3743..8973bc4f9 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/endpoints/endpoints.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/endpoints/endpoints.component.spec.ts @@ -1,74 +1,109 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; import { Router } from '@angular/router'; -import { RouterTestingModule } from '@angular/router/testing'; import { of } from 'rxjs'; -import { EndpointModel } from 'src/app/common/model/endpoint.model'; -import { HearingModel } from 'src/app/common/model/hearing.model'; -import { ParticipantModel } from 'src/app/common/model/participant.model'; -import { CancelPopupComponent } from 'src/app/popups/cancel-popup/cancel-popup.component'; -import { DiscardConfirmPopupComponent } from 'src/app/popups/discard-confirm-popup/discard-confirm-popup.component'; +import { EndpointsComponent } from './endpoints.component'; import { BookingService } from 'src/app/services/booking.service'; -import { ErrorService } from 'src/app/services/error.service'; -import { Logger } from 'src/app/services/logger'; import { VideoHearingsService } from 'src/app/services/video-hearings.service'; -import { SharedModule } from 'src/app/shared/shared.module'; -import { MockValues } from 'src/app/testing/data/test-objects'; -import { BreadcrumbComponent } from '../breadcrumb/breadcrumb.component'; -import { EndpointsComponent } from './endpoints.component'; -import { LaunchDarklyService, FeatureFlags } from 'src/app/services/launch-darkly.service'; +import { Logger } from 'src/app/services/logger'; +import { FeatureFlags, LaunchDarklyService } from 'src/app/services/launch-darkly.service'; +import { FormBuilder, ReactiveFormsModule } from '@angular/forms'; +import { HearingModel } from '../../common/model/hearing.model'; +import { VideoEndpointFormComponent } from './video-endpoint-form/video-endpoint-form.component'; +import { VideoEndpointListComponent } from './video-endpoint-list/video-endpoint-list.component'; +import { VideoEndpointItemComponent } from './video-endpoint-item/video-endpoint-item.component'; import { BreadcrumbStubComponent } from 'src/app/testing/stubs/breadcrumb-stub'; function initHearingRequest(): HearingModel { const newHearing = new HearingModel(); + newHearing.hearing_type_id = -1; newHearing.hearing_venue_id = -1; newHearing.scheduled_duration = 0; + newHearing.participants = [ + { + id: '1', + first_name: 'John', + last_name: 'Doe', + email: 'john@doe.com', + display_name: 'John Doe', + user_role_name: 'Representative' + }, + { + id: '2', + first_name: 'Chris', + last_name: 'Green', + email: 'chris@green,com', + display_name: 'Chris Green', + user_role_name: 'Representative' + }, + { + id: '3', + first_name: 'Jane', + last_name: 'Smith', + email: 'jane@smith.com', + display_name: 'Jane Smith', + user_role_name: 'Individual' + } + ]; + newHearing.endpoints = [ + { + id: '1', + displayName: 'Already Here', + defenceAdvocate: null, + sip: 'sip', + pin: 'pin', + username: 'test@existing.com', + contactEmail: 'test@existing.com' + } + ]; return newHearing; } -let videoHearingsServiceSpy: jasmine.SpyObj; -let launchDarklyServiceSpy: jasmine.SpyObj; -let routerSpy: jasmine.SpyObj; -const errorService: jasmine.SpyObj = jasmine.createSpyObj('ErrorService', ['handleError']); -let bookingServiceSpy: jasmine.SpyObj; - describe('EndpointsComponent', () => { let component: EndpointsComponent; let fixture: ComponentFixture; - const loggerSpy = jasmine.createSpyObj('Logger', ['error', 'debug', 'warn']); + let bookingServiceSpy: jasmine.SpyObj; + let videoHearingsServiceSpy: jasmine.SpyObj; + let routerSpy: jasmine.SpyObj; + let loggerSpy: jasmine.SpyObj; + let featureServiceSpy: jasmine.SpyObj; const newHearing = initHearingRequest(); - beforeEach(waitForAsync(() => { - launchDarklyServiceSpy = jasmine.createSpyObj('LaunchDarklyService', ['getFlag']); - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.multiDayBookingEnhancements).and.returnValue(of(false)); - - videoHearingsServiceSpy = jasmine.createSpyObj('VideoHearingsService', [ + beforeEach(async () => { + bookingServiceSpy = jasmine.createSpyObj('BookingService', ['removeEditMode', 'isEditMode', 'resetEditMode']); + videoHearingsServiceSpy = jasmine.createSpyObj('VideoHearingsService', [ 'getCurrentRequest', + 'isHearingAboutToStart', 'updateHearingRequest', - 'setBookingHasChanged', 'cancelRequest', - 'isHearingAboutToStart' + 'setBookingHasChanged' ]); - routerSpy = jasmine.createSpyObj('Router', ['navigate']); videoHearingsServiceSpy.getCurrentRequest.and.returnValue(newHearing); - bookingServiceSpy = jasmine.createSpyObj('BookingService', ['isEditMode', 'resetEditMode', 'removeEditMode']); - TestBed.configureTestingModule({ - imports: [SharedModule, RouterTestingModule], + routerSpy = jasmine.createSpyObj('Router', ['navigate']); + loggerSpy = jasmine.createSpyObj('Logger', ['debug']); + featureServiceSpy = jasmine.createSpyObj('LaunchDarklyService', ['getFlag']); + featureServiceSpy.getFlag.withArgs(FeatureFlags.multiDayBookingEnhancements).and.returnValue(of(false)); + + await TestBed.configureTestingModule({ + declarations: [ + EndpointsComponent, + VideoEndpointFormComponent, + VideoEndpointListComponent, + VideoEndpointItemComponent, + BreadcrumbStubComponent + ], providers: [ + { provide: BookingService, useValue: bookingServiceSpy }, { provide: VideoHearingsService, useValue: videoHearingsServiceSpy }, { provide: Router, useValue: routerSpy }, - { provide: ErrorService, useValue: errorService }, - { provide: BookingService, useValue: bookingServiceSpy }, { provide: Logger, useValue: loggerSpy }, - { provide: LaunchDarklyService, useValue: launchDarklyServiceSpy }, - { provide: BreadcrumbComponent, useValue: BreadcrumbStubComponent } + { provide: LaunchDarklyService, useValue: featureServiceSpy }, + FormBuilder ], - declarations: [EndpointsComponent, CancelPopupComponent, DiscardConfirmPopupComponent, BreadcrumbStubComponent] + imports: [ReactiveFormsModule] }).compileComponents(); - })); - beforeEach(() => { fixture = TestBed.createComponent(EndpointsComponent); component = fixture.componentInstance; fixture.detectChanges(); @@ -77,62 +112,19 @@ describe('EndpointsComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + it('should return true for hearing about to start', () => { + component.ngOnInit(); + videoHearingsServiceSpy.isHearingAboutToStart.and.returnValue(true); + expect(component.isHearingAboutToStart).toBe(true); + }); + it('should get booking data from storage', () => { component.ngOnInit(); fixture.detectChanges(); expect(component.hearing).toBeTruthy(); }); - it('should set return a form array', () => { - component.ngOnInit(); - expect(component.endpoints).toBeTruthy(); - }); - it('should have multiple endpoints', () => { - component.ngOnInit(); - component.endpoints.controls[0].get('displayName').setValue('100'); - component.addEndpoint(); - component.endpoints.controls[1].get('displayName').setValue('200'); - component.addEndpoint(); - expect(component.hasEndpoints).toBe(true); - }); - describe('when booking is multi day', () => { - beforeEach(() => { - const booking = new HearingModel(); - booking.isMultiDay = true; - videoHearingsServiceSpy.getCurrentRequest.and.returnValue(booking); - }); - it('should navigate to the summary page when next clicked and multi day booking enhancements are enabled', () => { - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.multiDayBookingEnhancements).and.returnValue(of(true)); - component.ngOnInit(); - component.saveEndpoints(); - expect(routerSpy.navigate).toHaveBeenCalledWith(['/summary']); - }); - it('should navigate to the other information page when next clicked and multi day booking enhancements are not enabled', () => { - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.multiDayBookingEnhancements).and.returnValue(of(false)); - component.ngOnInit(); - component.saveEndpoints(); - expect(routerSpy.navigate).toHaveBeenCalledWith(['/other-information']); - }); - }); - describe('when booking is not multi day', () => { - beforeEach(() => { - const booking = new HearingModel(); - booking.isMultiDay = false; - videoHearingsServiceSpy.getCurrentRequest.and.returnValue(booking); - }); - it('should navigate to the other information page when next clicked and multi day booking enhancements are enabled', () => { - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.multiDayBookingEnhancements).and.returnValue(of(true)); - component.ngOnInit(); - component.saveEndpoints(); - expect(routerSpy.navigate).toHaveBeenCalledWith(['/other-information']); - }); - it('should navigate to the other information page when next clicked and multi day booking enhancements are not enabled', () => { - launchDarklyServiceSpy.getFlag.withArgs(FeatureFlags.multiDayBookingEnhancements).and.returnValue(of(false)); - component.ngOnInit(); - component.saveEndpoints(); - expect(routerSpy.navigate).toHaveBeenCalledWith(['/other-information']); - }); - }); it('should show a confirmation popup if cancel clicked in new mode', () => { bookingServiceSpy.isEditMode.and.returnValue(false); component.ngOnInit(); @@ -180,208 +172,113 @@ describe('EndpointsComponent', () => { expect(component.attemptingDiscardChanges).toBeFalsy(); expect(routerSpy.navigate).toHaveBeenCalledWith(['/summary']); }); - it('it should validate display names on add another click and show error for duplicates', () => { - component.ngOnInit(); - component.endpoints.controls[0].get('displayName').setValue('200'); - component.addEndpoint(); - component.endpoints.controls[1].get('displayName').setValue('200'); - component.addEndpoint(); - expect(component.duplicateDa).toBe(true); - expect(component.failedValidation).toBe(true); - }); - it('it should validate display names on next click and show error for duplicates', () => { - component.ngOnInit(); - component.endpoints.controls[0].get('displayName').setValue('200'); - component.addEndpoint(); - component.endpoints.controls[1].get('displayName').setValue('200'); - component.saveEndpoints(); - expect(component.duplicateDa).toBe(true); - expect(component.failedValidation).toBe(true); - }); - it('it should validate display names on next click and navigate to other information page if validations pass', () => { - component.ngOnInit(); - component.endpoints.controls[0].get('displayName').setValue('200'); - component.addEndpoint(); - component.endpoints.controls[1].get('displayName').setValue('201'); - component.saveEndpoints(); - expect(component.duplicateDa).toBe(false); - expect(component.failedValidation).toBe(false); - expect(component.hearing.endpoints[0].displayName).toBe('200'); - expect(component.hearing.endpoints[1].displayName).toBe('201'); - expect(videoHearingsServiceSpy.updateHearingRequest).toHaveBeenCalled(); - expect(routerSpy.navigate).toHaveBeenCalledWith(['/other-information']); - }); - it('it should validate defence advocate on next click and navigate to other information page for defence adv none', () => { - component.ngOnInit(); - videoHearingsServiceSpy.isHearingAboutToStart.and.returnValue(false); - component.endpoints.controls[0].get('displayName').setValue('200'); - component.saveEndpoints(); - expect(component.duplicateDa).toBe(false); - expect(component.failedValidation).toBe(false); - expect(component.hearing.endpoints[0].displayName).toBe('200'); - expect(component.hearing.endpoints[0].defenceAdvocate).toBeNull(); - expect(videoHearingsServiceSpy.updateHearingRequest).toHaveBeenCalled(); - expect(routerSpy.navigate).toHaveBeenCalledWith(['/other-information']); - }); - it('should return true for hearing about to start', () => { - component.ngOnInit(); - videoHearingsServiceSpy.isHearingAboutToStart.and.returnValue(true); - expect(component.isHearingAboutToStart).toBe(true); - }); - - it('it should validate fields on next click and navigate to other information page if validations pass', () => { - component.ngOnInit(); - videoHearingsServiceSpy.isHearingAboutToStart.and.returnValue(false); - component.endpoints.controls[0].get('displayName').setValue('200'); - component.endpoints.controls[0].get('defenceAdvocate').setValue('username@hmcts.net'); - component.addEndpoint(); - component.endpoints.controls[1].get('displayName').setValue('201'); - component.endpoints.controls[1].get('defenceAdvocate').setValue('username1@hmcts.net'); - component.saveEndpoints(); - expect(component.duplicateDa).toBe(false); - expect(component.failedValidation).toBe(false); - expect(component.hearing.endpoints[0].displayName).toBe('200'); - expect(component.hearing.endpoints[0].defenceAdvocate).toBe('username@hmcts.net'); - expect(component.hearing.endpoints[1].displayName).toBe('201'); - expect(component.hearing.endpoints[1].defenceAdvocate).toBe('username1@hmcts.net'); - expect(videoHearingsServiceSpy.updateHearingRequest).toHaveBeenCalled(); - expect(routerSpy.navigate).toHaveBeenCalledWith(['/other-information']); + describe('when booking is multi day', () => { + beforeEach(() => { + const booking = new HearingModel(); + booking.isMultiDay = true; + videoHearingsServiceSpy.getCurrentRequest.and.returnValue(booking); + }); + it('should navigate to the summary page when next clicked and multi day booking enhancements are enabled', () => { + featureServiceSpy.getFlag.withArgs(FeatureFlags.multiDayBookingEnhancements).and.returnValue(of(true)); + component.ngOnInit(); + component.saveEndpoints(); + expect(routerSpy.navigate).toHaveBeenCalledWith(['/summary']); + }); + it('should navigate to the other information page when next clicked and multi day booking enhancements are not enabled', () => { + featureServiceSpy.getFlag.withArgs(FeatureFlags.multiDayBookingEnhancements).and.returnValue(of(false)); + component.ngOnInit(); + component.saveEndpoints(); + expect(routerSpy.navigate).toHaveBeenCalledWith(['/other-information']); + }); }); + describe('when booking is not multi day', () => { + beforeEach(() => { + const booking = new HearingModel(); + booking.isMultiDay = false; + videoHearingsServiceSpy.getCurrentRequest.and.returnValue(booking); + }); - it('it should filter "Representative" user-types only as valid defenceAdvocates for JVM', () => { - // arrange - newHearing.participants = [ - { user_role_name: 'Representative', display_name: 'Counsel', hearing_role_name: 'Counsel', case_role_name: 'Appellant' }, - { user_role_name: 'Individual', display_name: 'Employer', hearing_role_name: 'Employer', case_role_name: 'Appellant' }, - { user_role_name: 'Representative', display_name: 'Solicitor', hearing_role_name: 'Solicitor', case_role_name: 'Appellant' }, - { user_role_name: 'Representative', display_name: 'Barrister', hearing_role_name: 'Barrister', case_role_name: 'Appellant' }, - { - user_role_name: 'Representative', - display_name: 'pro-bono representative', - hearing_role_name: 'pro-bono representative', - case_role_name: 'ELAAS' - }, - { - user_role_name: 'Representative', - display_name: 'Representative', - hearing_role_name: 'Representative', - case_role_name: 'Appellant' - }, - { user_role_name: 'Representative', display_name: 'Advocate1', hearing_role_name: 'Advocate', case_role_name: 'Appellant' }, - { - user_role_name: 'Individual', - display_name: 'Litigant in person', - hearing_role_name: 'Litigant in person', - case_role_name: 'Appellant' - }, - { user_role_name: 'Representative', display_name: 'Advocate2', hearing_role_name: 'Advocate', case_role_name: 'Respondent' } - ]; - videoHearingsServiceSpy.isHearingAboutToStart.and.returnValue(false); - videoHearingsServiceSpy.getCurrentRequest.and.returnValue(newHearing); - // act - component.ngOnInit(); - // assert - // Current implementation of populateDefenceAdvocates() inserts an empty record at position[0] - expect(component.availableDefenceAdvocates[1].displayName).toBe('Counsel'); - expect(component.availableDefenceAdvocates[2].displayName).toBe('Solicitor'); - expect(component.availableDefenceAdvocates[3].displayName).toBe('Barrister'); - expect(component.availableDefenceAdvocates[4].displayName).toBe('pro-bono representative'); - expect(component.availableDefenceAdvocates[5].displayName).toBe('Representative'); - expect(component.availableDefenceAdvocates[6].displayName).toBe('Advocate1'); - expect(component.availableDefenceAdvocates[7].displayName).toBe('Advocate2'); + it('should navigate to the other information page when next clicked and multi day booking enhancements are enabled', () => { + featureServiceSpy.getFlag.withArgs(FeatureFlags.multiDayBookingEnhancements).and.returnValue(of(true)); + component.ngOnInit(); + component.videoEndpoints = [{ id: '1', displayName: 'Test', defenceAdvocate: null }]; + component.saveEndpoints(); + expect(routerSpy.navigate).toHaveBeenCalledWith(['/other-information']); + }); + it('should navigate to the other information page when next clicked and multi day booking enhancements are not enabled', () => { + featureServiceSpy.getFlag.withArgs(FeatureFlags.multiDayBookingEnhancements).and.returnValue(of(false)); + component.ngOnInit(); + component.saveEndpoints(); + expect(routerSpy.navigate).toHaveBeenCalledWith(['/other-information']); + }); }); - it('it should validate form array on next click and navigate to summary page in edit mode', () => { - videoHearingsServiceSpy.isHearingAboutToStart.and.returnValue(false); - bookingServiceSpy.isEditMode.and.returnValue(true); - component.ngOnInit(); - const existinghearing = new HearingModel(); - existinghearing.case_type = 'Case type'; - const eps: EndpointModel[] = []; - let ep = new EndpointModel(); - ep.displayName = 'displayname1'; - ep.defenceAdvocate = '12345'; - eps.push(ep); - ep = new EndpointModel(); - ep.displayName = 'displayname1'; - ep.defenceAdvocate = '11223'; - existinghearing.endpoints = eps; - - component.hearing = existinghearing; - - component.endpoints.controls[0].get('displayName').setValue('new display name'); - component.endpoints.controls[0].get('defenceAdvocate').setValue('user@hmcts.net'); - component.saveEndpoints(); - expect(component.failedValidation).toBe(false); - expect(component.hearing.endpoints[0].displayName).toBe('new display name'); - expect(component.hearing.endpoints[0].defenceAdvocate).toBe('user@hmcts.net'); - expect(videoHearingsServiceSpy.updateHearingRequest).toHaveBeenCalled(); + describe('onEndpoitnAdded', () => { + it('should add endpoint', () => { + const endpoint = { id: '1', displayName: 'Test', defenceAdvocate: null }; + component.onEndpointAdded(endpoint); + expect(component.videoEndpoints).toContain(endpoint); + }); - expect(routerSpy.navigate).toHaveBeenCalledWith(['/summary']); + it('should not add an endpoint when the display name already exists', () => { + const endpoint = { id: '1', displayName: 'Test', defenceAdvocate: null }; + component.videoEndpoints = [endpoint]; + component.onEndpointAdded(endpoint); + expect(component.videoEndpoints.length).toBe(1); + }); }); - it('it should remove an endpoint from the endpoint array on remove click', () => { - videoHearingsServiceSpy.isHearingAboutToStart.and.returnValue(false); - component.ngOnInit(); - component.endpoints.controls[0].get('displayName').setValue('200'); - component.endpoints.controls[0].get('defenceAdvocate').setValue('username@hmcts.net'); - component.addEndpoint(); - component.endpoints.controls[1].get('displayName').setValue('201'); - component.endpoints.controls[1].get('defenceAdvocate').setValue('username1@hmcts.net'); - component.addEndpoint(); - component.endpoints.controls[2].get('displayName').setValue('202'); - component.endpoints.controls[2].get('defenceAdvocate').setValue('username2@hmcts.net'); + describe('onEndpointUpdated', () => { + beforeEach(() => { + component.videoEndpoints = [ + { id: '1', displayName: 'Test', defenceAdvocate: null }, + { id: '2', displayName: 'Test2', defenceAdvocate: null } + ]; + }); - component.removeEndpoint(1); - component.saveEndpoints(); - expect(component.hearing.endpoints.length).toBe(2); + it('should update endpoint', () => { + const endpoint = { id: '1', displayName: 'Test', defenceAdvocate: null }; + component.videoEndpoints = [endpoint]; + const updatedEndpoint = { id: '1', displayName: 'Updated', defenceAdvocate: null }; + component.onEndpointUpdated({ original: endpoint, updated: updatedEndpoint }); + expect(component.videoEndpoints).toContain(updatedEndpoint); + }); + + it('should not update endpoint when the original endpoint does not exist', () => { + const endpoint = { id: '1', displayName: 'DoesNotExist', defenceAdvocate: null }; + const updatedEndpoint = { id: '1', displayName: 'Updated', defenceAdvocate: null }; + component.onEndpointUpdated({ original: endpoint, updated: updatedEndpoint }); + expect(component.videoEndpoints).not.toContain(endpoint); + }); }); - it('it should not remove an endpoint from the endpoint array on remove click when hearing is about to start', () => { - videoHearingsServiceSpy.isHearingAboutToStart.and.returnValue(true); - component.ngOnInit(); + describe('onEndpointSelectedForDeletion', () => { + beforeEach(() => { + component.videoEndpoints = [ + { id: '1', displayName: 'Test', defenceAdvocate: null }, + { id: '2', displayName: 'Test2', defenceAdvocate: null } + ]; + }); - for (let index = 0; index <= 2; index++) { - component.addEndpoint(); - component.endpoints.controls[index].get('displayName').setValue(`20${index}`); - component.endpoints.controls[index].get('defenceAdvocate').setValue(`username${index}@hmcts.net`); - } + it('should delete endpoint', () => { + const endpoint = { id: '1', displayName: 'Test', defenceAdvocate: null }; + component.onEndpointSelectedForDeletion(endpoint); + expect(component.videoEndpoints).not.toContain(endpoint); + }); - component.removeEndpoint(1); - component.saveEndpoints(); - expect(component.hearing.endpoints.length).toBe(3); - }); - it('should map participant list to defence advocate model', () => { - videoHearingsServiceSpy.isHearingAboutToStart.and.returnValue(false); - const participantModel = new ParticipantModel(); - participantModel.id = '1000'; - participantModel.email = 'username@hmcts.net'; - participantModel.display_name = 'display name'; - component.ngOnInit(); - const dA = component.mapParticipantsToDefenceAdvocateModel(participantModel); - expect(dA).toBeTruthy(); - expect(dA.id).toBe('1000'); - expect(dA.contactEmail).toBe('username@hmcts.net'); - expect(dA.displayName).toBe('display name'); - expect(dA.isSelected).toBe(null); - }); - it('should return the username from id', () => { - videoHearingsServiceSpy.isHearingAboutToStart.and.returnValue(false); - const participantModel = new ParticipantModel(); - participantModel.id = '1000'; - participantModel.email = 'username@hmcts.net'; - participantModel.display_name = 'display name'; - component.hearing.participants.push(participantModel); - component.ngOnInit(); - let result = component.getEmailFromId('1000'); - expect(result).toBe('username@hmcts.net'); - result = component.getEmailFromId('1001'); - expect(result).toBe('1001'); + it('should not delete endpoint when the endpoint does not exist', () => { + const endpoint = { id: '3', displayName: 'Test3', defenceAdvocate: null }; + component.onEndpointSelectedForDeletion(endpoint); + expect(component.videoEndpoints.length).toBe(2); + }); }); - it('should unsubscribe all subcription on destroy', () => { - videoHearingsServiceSpy.isHearingAboutToStart.and.returnValue(false); - component.ngOnDestroy(); - expect(component.$subscriptions[0].closed).toBe(true); + + describe('onEndpointSelectedForEdit', () => { + it('should set endpoint to edit', () => { + const endpoint = { id: '1', displayName: 'Test', defenceAdvocate: null }; + component.onEndpointSelectedForEdit(endpoint); + expect(component.videoEndpointToEdit).toBe(endpoint); + }); }); }); From f85d07efa64e08921db22864ad42d220f803a4b8 Mon Sep 17 00:00:00 2001 From: marcogagliardi Date: Mon, 17 Jun 2024 11:57:21 +0100 Subject: [PATCH 14/25] Update hearing-details.component.html --- .../hearing-details/hearing-details.component.html | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/hearing-details/hearing-details.component.html b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/hearing-details/hearing-details.component.html index e7b8c6a20..0de1c0285 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/hearing-details/hearing-details.component.html +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/bookings-list/hearing-details/hearing-details.component.html @@ -45,11 +45,7 @@

    Booki

    -
    +
    Allocated to:
    From 8f8ef32217f7b686296ad7e3cd31ed02df182e6d Mon Sep 17 00:00:00 2001 From: marcogagliardi Date: Mon, 17 Jun 2024 12:04:20 +0100 Subject: [PATCH 15/25] Update create-hearing.component.ts --- .../app/booking/create-hearing/create-hearing.component.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/create-hearing/create-hearing.component.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/create-hearing/create-hearing.component.ts index 07351b92a..0675551dc 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/create-hearing/create-hearing.component.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/booking/create-hearing/create-hearing.component.ts @@ -79,7 +79,12 @@ export class CreateHearingComponent extends BookingBaseComponent implements OnIn this.logger.debug(`${this.loggerPrefix} Checking for existing hearing.`); this.selectedCaseType = this.hearing.case_type; - return; + if (this.hearing.case_type) { + this.selectedCaseType = this.hearing.case_type; + return; + } else { + this.selectedCaseType = Constants.PleaseSelect; + } if (!!this.hearing.hearing_type_name && !!this.hearing.case_type) { this.selectedCaseType = this.hearing.case_type; From 960bc4dea84abbb78b3cc774c99f954e3faeb149 Mon Sep 17 00:00:00 2001 From: SwapnaVersion1 <157039140+SwapnaVersion1@users.noreply.github.com> Date: Mon, 17 Jun 2024 13:32:22 +0100 Subject: [PATCH 16/25] Update azure-pipelines.sds.pr-release.yml --- azure-pipelines.sds.pr-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.sds.pr-release.yml b/azure-pipelines.sds.pr-release.yml index 4202a984c..40e64575a 100644 --- a/azure-pipelines.sds.pr-release.yml +++ b/azure-pipelines.sds.pr-release.yml @@ -5,7 +5,7 @@ resources: - repository: azTemplates type: github name: hmcts/azure-devops-templates - ref: master + ref: fix_docker_compose endpoint: hmcts pool: From db72ab7ba01100b3b836d5e26d19f365d9d5f9aa Mon Sep 17 00:00:00 2001 From: SwapnaVersion1 <157039140+SwapnaVersion1@users.noreply.github.com> Date: Mon, 17 Jun 2024 14:03:09 +0100 Subject: [PATCH 17/25] Update azure-pipelines.sds.pr-release.yml --- azure-pipelines.sds.pr-release.yml | 42 +----------------------------- 1 file changed, 1 insertion(+), 41 deletions(-) diff --git a/azure-pipelines.sds.pr-release.yml b/azure-pipelines.sds.pr-release.yml index 40e64575a..d8bf318fc 100644 --- a/azure-pipelines.sds.pr-release.yml +++ b/azure-pipelines.sds.pr-release.yml @@ -5,7 +5,7 @@ resources: - repository: azTemplates type: github name: hmcts/azure-devops-templates - ref: fix_docker_compose + ref: fix_docker_compose_1 endpoint: hmcts pool: @@ -23,46 +23,6 @@ variables: value: false stages: - ##################################################### - # CI Build Checks. ################################## - - stage: CI_Build - displayName: CI Build - variables: - - template: variables/shared.yaml - jobs: - - job: CI_Helm - displayName: "Helm CI" - steps: - - checkout: self - - - template: templates\Containerisation\helm\helm-lint.yaml@azTemplates - parameters: - chartPath: ${{ variables.chartPath }} - chartValuesPath: ${{ variables.chartPath }} - helmVersion: '3.12.3' - - - job: UnitAndIntegrationTests - displayName: "Unit and Integration Tests" - steps: - - checkout: self - - - template: templates/dotnet/build-test-analyse.yml@azTemplates - parameters: - dotnetVersion: ${{ variables.dotnetVersion }} - nugetConfigPath: nuget.config - appName: ${{ variables.appName }} - dockerComposeTestFile: docker-compose.tests.yml - publishNodeTests: true - nodeTestResultFolder: $(System.DefaultWorkingDirectory)/AdminWebsite/AdminWebsite/ClientApp - sonarExtraProperties: | - sonar.exclusions=**/node_modules/**, **/*.spec.ts, *.spec.ts, **/ClientApp/src/*, **/ClientApp/src/app/testing/**, **/ClientApp/coverage/**/*, **/Startup.cs, **/Program.cs, **/ConfigureServicesExtensions.cs, **/Swagger/*.cs, **/src/app/testing/data/*.ts, **/auth-config.module.ts - sonar.cs.opencover.reportsPaths=$(System.DefaultWorkingDirectory)/coverage.opencover.xml - sonar.javascript.lcov.reportPaths=**/ClientApp/coverage/lcov.info - sonar.typescript.exclusions=**/node_modules/**, **/typings.d.ts, **/main.ts, **/environments/environment*.ts, **/*routing.module.ts, **/api-client.ts - sonar.coverage.exclusions=**/AdminWebsite/Configuration/**, **/AdminWebsite/Security/**, **/AdminWebsite.Testing.Common/**, **/AdminWebsite/Views/*, **/AdminWebsite/Pages/*, **/AdminWebsite.AcceptanceTests/*, **/AdminWebsite.*Tests/* - sonar.issue.ignore.multicriteria=e1 - sonar.issue.ignore.multicriteria.e1.ruleKey=typescript:S6544 - sonar.issue.ignore.multicriteria.e1.resourceKey=**/*.ts ##################################################### # Build Docker Image. ############################### From b4ba9840e3a6185b7fe5e58a89f9d7bb628392d7 Mon Sep 17 00:00:00 2001 From: SwapnaVersion1 <157039140+SwapnaVersion1@users.noreply.github.com> Date: Mon, 17 Jun 2024 14:05:34 +0100 Subject: [PATCH 18/25] Update azure-pipelines.sds.pr-release.yml --- azure-pipelines.sds.pr-release.yml | 40 ++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/azure-pipelines.sds.pr-release.yml b/azure-pipelines.sds.pr-release.yml index d8bf318fc..d9ad63cbd 100644 --- a/azure-pipelines.sds.pr-release.yml +++ b/azure-pipelines.sds.pr-release.yml @@ -23,6 +23,46 @@ variables: value: false stages: + ##################################################### + # CI Build Checks. ################################## + - stage: CI_Build + displayName: CI Build + variables: + - template: variables/shared.yaml + jobs: + - job: CI_Helm + displayName: "Helm CI" + steps: + - checkout: self + + - template: templates\Containerisation\helm\helm-lint.yaml@azTemplates + parameters: + chartPath: ${{ variables.chartPath }} + chartValuesPath: ${{ variables.chartPath }} + helmVersion: '3.12.3' + + - job: UnitAndIntegrationTests + displayName: "Unit and Integration Tests" + steps: + - checkout: self + + - template: templates/dotnet/build-test-analyse.yml@azTemplates + parameters: + dotnetVersion: ${{ variables.dotnetVersion }} + nugetConfigPath: nuget.config + appName: ${{ variables.appName }} + dockerComposeTestFile: docker-compose.tests.yml + publishNodeTests: true + nodeTestResultFolder: $(System.DefaultWorkingDirectory)/AdminWebsite/AdminWebsite/ClientApp + sonarExtraProperties: | + sonar.exclusions=**/node_modules/**, **/*.spec.ts, *.spec.ts, **/ClientApp/src/*, **/ClientApp/src/app/testing/**, **/ClientApp/coverage/**/*, **/Startup.cs, **/Program.cs, **/ConfigureServicesExtensions.cs, **/Swagger/*.cs, **/src/app/testing/data/*.ts, **/auth-config.module.ts + sonar.cs.opencover.reportsPaths=$(System.DefaultWorkingDirectory)/coverage.opencover.xml + sonar.javascript.lcov.reportPaths=**/ClientApp/coverage/lcov.info + sonar.typescript.exclusions=**/node_modules/**, **/typings.d.ts, **/main.ts, **/environments/environment*.ts, **/*routing.module.ts, **/api-client.ts + sonar.coverage.exclusions=**/AdminWebsite/Configuration/**, **/AdminWebsite/Security/**, **/AdminWebsite.Testing.Common/**, **/AdminWebsite/Views/*, **/AdminWebsite/Pages/*, **/AdminWebsite.AcceptanceTests/*, **/AdminWebsite.*Tests/* + sonar.issue.ignore.multicriteria=e1 + sonar.issue.ignore.multicriteria.e1.ruleKey=typescript:S6544 + sonar.issue.ignore.multicriteria.e1.resourceKey=**/*.ts ##################################################### # Build Docker Image. ############################### From 6621c38155fda22dc1fb50226416be786b8b8540 Mon Sep 17 00:00:00 2001 From: SwapnaVersion1 <157039140+SwapnaVersion1@users.noreply.github.com> Date: Mon, 17 Jun 2024 14:23:51 +0100 Subject: [PATCH 19/25] Update azure-pipelines.sds.pr-release.yml for Azure Pipelines --- azure-pipelines.sds.pr-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.sds.pr-release.yml b/azure-pipelines.sds.pr-release.yml index d9ad63cbd..40e64575a 100644 --- a/azure-pipelines.sds.pr-release.yml +++ b/azure-pipelines.sds.pr-release.yml @@ -5,7 +5,7 @@ resources: - repository: azTemplates type: github name: hmcts/azure-devops-templates - ref: fix_docker_compose_1 + ref: fix_docker_compose endpoint: hmcts pool: From 76911ece830cabf3dccc123c7f7a5f2dea265adb Mon Sep 17 00:00:00 2001 From: SwapnaVersion1 <157039140+SwapnaVersion1@users.noreply.github.com> Date: Mon, 17 Jun 2024 18:09:19 +0100 Subject: [PATCH 20/25] Update docker-compose.yml --- AdminWebsite/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AdminWebsite/docker-compose.yml b/AdminWebsite/docker-compose.yml index f645fb7dc..0cd00e2f3 100644 --- a/AdminWebsite/docker-compose.yml +++ b/AdminWebsite/docker-compose.yml @@ -1,4 +1,4 @@ -version: '3.4' + services: adminweb: From 9fa9e368a73bc1afb4454dd70460b36ae6198242 Mon Sep 17 00:00:00 2001 From: SwapnaVersion1 <157039140+SwapnaVersion1@users.noreply.github.com> Date: Mon, 17 Jun 2024 19:15:53 +0100 Subject: [PATCH 21/25] Update docker-compose.yml --- AdminWebsite/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AdminWebsite/docker-compose.yml b/AdminWebsite/docker-compose.yml index 0cd00e2f3..f645fb7dc 100644 --- a/AdminWebsite/docker-compose.yml +++ b/AdminWebsite/docker-compose.yml @@ -1,4 +1,4 @@ - +version: '3.4' services: adminweb: From da066d4a85be5fc9f637d9b5559562f304964222 Mon Sep 17 00:00:00 2001 From: SwapnaVersion1 <157039140+SwapnaVersion1@users.noreply.github.com> Date: Mon, 17 Jun 2024 19:18:23 +0100 Subject: [PATCH 22/25] Update docker-compose.yml --- AdminWebsite/docker-compose.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/AdminWebsite/docker-compose.yml b/AdminWebsite/docker-compose.yml index f645fb7dc..9022a600c 100644 --- a/AdminWebsite/docker-compose.yml +++ b/AdminWebsite/docker-compose.yml @@ -1,4 +1,3 @@ -version: '3.4' services: adminweb: From efe0c00cf3d8cea7a7d510cd79961130cddf686b Mon Sep 17 00:00:00 2001 From: SwapnaVersion1 <157039140+SwapnaVersion1@users.noreply.github.com> Date: Tue, 18 Jun 2024 10:48:44 +0100 Subject: [PATCH 23/25] Update azure-pipelines.sds.pr-release.yml for Azure Pipelines --- azure-pipelines.sds.pr-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.sds.pr-release.yml b/azure-pipelines.sds.pr-release.yml index 40e64575a..fc1539ef6 100644 --- a/azure-pipelines.sds.pr-release.yml +++ b/azure-pipelines.sds.pr-release.yml @@ -5,7 +5,7 @@ resources: - repository: azTemplates type: github name: hmcts/azure-devops-templates - ref: fix_docker_compose + ref: fix_upgrade_docker2 endpoint: hmcts pool: From 7512762f52aae154b207532f90eaaf0849f587dd Mon Sep 17 00:00:00 2001 From: SwapnaVersion1 <157039140+SwapnaVersion1@users.noreply.github.com> Date: Tue, 18 Jun 2024 13:58:35 +0100 Subject: [PATCH 24/25] Update azure-pipelines.sds.pr-release.yml for Azure Pipelines --- azure-pipelines.sds.pr-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.sds.pr-release.yml b/azure-pipelines.sds.pr-release.yml index fc1539ef6..40e64575a 100644 --- a/azure-pipelines.sds.pr-release.yml +++ b/azure-pipelines.sds.pr-release.yml @@ -5,7 +5,7 @@ resources: - repository: azTemplates type: github name: hmcts/azure-devops-templates - ref: fix_upgrade_docker2 + ref: fix_docker_compose endpoint: hmcts pool: From 1d4d4fb33ef60b2f362945d6d7b965ee7ea6827c Mon Sep 17 00:00:00 2001 From: SwapnaVersion1 <157039140+SwapnaVersion1@users.noreply.github.com> Date: Tue, 18 Jun 2024 16:03:27 +0100 Subject: [PATCH 25/25] Update azure-pipelines.sds.pr-release.yml --- azure-pipelines.sds.pr-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.sds.pr-release.yml b/azure-pipelines.sds.pr-release.yml index 40e64575a..f0350d21b 100644 --- a/azure-pipelines.sds.pr-release.yml +++ b/azure-pipelines.sds.pr-release.yml @@ -5,7 +5,7 @@ resources: - repository: azTemplates type: github name: hmcts/azure-devops-templates - ref: fix_docker_compose + ref: fixx_upgrade_docker2 endpoint: hmcts pool: