Skip to content

Commit

Permalink
Update query-details.component.ts (#1844)
Browse files Browse the repository at this point in the history
* Update query-details.component.ts

* version

* fix test failing - For Test purposes only

* Update sonar-project.properties

* update

* test update

* Update sonar-project.properties

* Update query-check-your-answers.component.ts

* Toggle back link

* update test

* Update query-details.component.ts

* Update query-check-your-answers.component.ts

* toolkit update

* Update query-check-your-answers.component.ts

* update test

* error message added for query already responded to

* toolkit version

* Test added

* prevent user from responding multiple times to a query

* code tidy

* displays the latest query

* toolkit version update

* update code to only function when responds to a query

* code tidy

* code tidy

* Update query-check-your-answers.component.spec.ts

* Update query-write-respond-to-query.component.spec.ts

* version updated

---------

Co-authored-by: RiteshHMCTS <[email protected]>
Co-authored-by: Ritesh Dsouza <[email protected]>
  • Loading branch information
3 people authored Feb 5, 2025
1 parent 919e7dd commit 0d01c66
Show file tree
Hide file tree
Showing 13 changed files with 363 additions and 96 deletions.
3 changes: 3 additions & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## RELEASE NOTES

### Version 7.1.35
**EXUI-2711** Review font and grammer in the query management screens

### Version 7.1.34
**EXUI-2524** Review font and grammer in the query management screens

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@hmcts/ccd-case-ui-toolkit",
"version": "7.1.34",
"version": "7.1.35",
"engines": {
"node": ">=18.19.0"
},
Expand Down
2 changes: 1 addition & 1 deletion projects/ccd-case-ui-toolkit/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@hmcts/ccd-case-ui-toolkit",
"version": "7.1.34",
"version": "7.1.35",
"engines": {
"node": ">=18.19.0"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component, DebugElement } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing';
import { plainToClassFromExist } from 'class-transformer';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,8 +391,8 @@ describe('QueryCheckYourAnswersComponent', () => {

beforeEach(async () => {
router = jasmine.createSpyObj('Router', ['navigate']);
workAllocationService = jasmine.createSpyObj('WorkAllocationService', ['searchTasks']);
workAllocationService.searchTasks.and.returnValue(of(response));
workAllocationService = jasmine.createSpyObj('WorkAllocationService', ['getTasksByCaseIdAndEventId', 'completeTask']);
workAllocationService.getTasksByCaseIdAndEventId.and.returnValue(of(response));
sessionStorageService = jasmine.createSpyObj<SessionStorageService>('sessionStorageService', ['getItem']);
sessionStorageService.getItem.and.returnValue(JSON.stringify(userDetails));
casesService = jasmine.createSpyObj('casesService', ['createEvent', 'getCaseViewV2']);
Expand All @@ -414,7 +414,7 @@ describe('QueryCheckYourAnswersComponent', () => {
{ provide: WorkAllocationService, useValue: workAllocationService },
{ provide: SessionStorageService, useValue: sessionStorageService },
{ provide: Router, useValue: router },
{ provide: QualifyingQuestionService , useValue: qualifyingQuestionService }
{ provide: QualifyingQuestionService, useValue: qualifyingQuestionService }
]
})
.compileComponents();
Expand All @@ -430,6 +430,7 @@ describe('QueryCheckYourAnswersComponent', () => {
isHearingRelated: new FormControl('', Validators.required),
attachments: new FormControl([mockAttachment])
});
component['tid'] = '1';
component.formGroup.get('isHearingRelated')?.setValue(true);
nativeElement = fixture.debugElement.nativeElement;
fixture.detectChanges();
Expand Down Expand Up @@ -576,32 +577,7 @@ describe('QueryCheckYourAnswersComponent', () => {
});
});

describe('searchAndCompleteTask', () => {
it('should call search task', () => {
component.queryCreateContext = QueryCreateContext.NEW_QUERY;
component.searchAndCompleteTask();
});
});

describe('submit', () => {
it('should call search task', () => {
component.searchAndCompleteTask();
fixture.detectChanges();
const searchParameter = { ccdId: '1' } as TaskSearchParameter;
expect(workAllocationService.searchTasks).toHaveBeenCalledWith(searchParameter);
});

it('should trigger event completion', () => {
component.searchAndCompleteTask();
fixture.detectChanges();
const eventCompletionParams: EventCompletionParams = {
caseId: '1',
eventId: 'queryManagementRespondQuery',
task: response.tasks[0]
};
expect(component.eventCompletionParams).toEqual(eventCompletionParams);
});

it('should log an error when fieldId is missing', () => {
spyOn(console, 'error');
component.fieldId = null;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { forkJoin, Observable, Subscription } from 'rxjs';
import { take } from 'rxjs/operators';
import {
CaseEventTrigger,
CaseField,
CaseView,
CaseViewTrigger,
ErrorMessage,
TaskSearchParameter
ErrorMessage
} from '../../../../../../../lib/shared/domain';
import { SessionStorageService } from '../../../../../services';
import { EventCompletionParams } from '../../../../case-editor/domain/event-completion-params.model';
Expand Down Expand Up @@ -42,6 +41,7 @@ export class QueryCheckYourAnswersComponent implements OnInit, OnDestroy {
private caseViewTrigger: CaseViewTrigger;
public caseDetails: CaseView;
private queryId: string;
private tid: string;
private createEventSubscription: Subscription;
private searchTasksSubscription: Subscription;

Expand All @@ -52,6 +52,7 @@ export class QueryCheckYourAnswersComponent implements OnInit, OnDestroy {
public attachments: FormDocument[];

public errorMessages: ErrorMessage[] = [];
public filteredTask = [];

constructor(
private readonly route: ActivatedRoute,
Expand All @@ -65,6 +66,8 @@ export class QueryCheckYourAnswersComponent implements OnInit, OnDestroy {

public ngOnInit(): void {
this.queryId = this.route.snapshot.params.qid;
this.tid = this.route.snapshot.queryParams?.tid;

this.caseNotifier.caseView.pipe(take(1)).subscribe((caseDetails) => {
this.caseDetails = caseDetails;

Expand All @@ -82,6 +85,23 @@ export class QueryCheckYourAnswersComponent implements OnInit, OnDestroy {
this.getDocumentAttachments();

this.setCaseQueriesCollectionData();

if (this.queryCreateContext === QueryCreateContext.RESPOND) {
this.searchTasksSubscription = this.workAllocationService.getTasksByCaseIdAndEventId(this.RESPOND_TO_QUERY_EVENT_TRIGGER_ID, this.caseDetails.case_id, this.caseDetails.case_type.id, this.caseDetails.case_type.jurisdiction.id)
.subscribe({
next: (response: any) => {
// Filter task by query id
if (response.tasks?.length > 1) {
this.filteredTask = response.tasks?.find((task) => task.case_id === this.tid);
} else {
this.filteredTask = response.tasks;
}
},
error: (error) => {
console.error('Error in searchTasksSubscription:', error);
}
});
}
}

public ngOnDestroy(): void {
Expand All @@ -108,7 +128,29 @@ export class QueryCheckYourAnswersComponent implements OnInit, OnDestroy {
}

const data = this.generateCaseQueriesCollectionData();
this.createEventSubscription = this.casesService.createEvent(this.caseDetails, {
const createEvent$ = this.createEvent(data);

if (this.queryCreateContext === QueryCreateContext.RESPOND) {
const completeTask$ = this.workAllocationService.completeTask(
this.filteredTask[0].id,
this.caseViewTrigger.name
);
this.createEventSubscription = forkJoin([createEvent$, completeTask$]).subscribe({
next: ([createEventResponse, tasksResponse]: [any, any]) => {
this.finaliseSubmission();
},
error: (error) => this.handleError(error)
});
} else {
this.createEventSubscription = createEvent$.subscribe({
next: () => this.finaliseSubmission(),
error: (error) => this.handleError(error)
});
}
}

private createEvent(data: any): Observable<any> {
return this.casesService.createEvent(this.caseDetails, {
data,
event: {
id: this.caseViewTrigger?.id,
Expand All @@ -117,41 +159,17 @@ export class QueryCheckYourAnswersComponent implements OnInit, OnDestroy {
},
event_token: this.eventData?.event_token,
ignore_warning: false
}).subscribe(
() => {
// Search and complete task
this.searchAndCompleteTask();
// Emit query submitted event
this.querySubmitted.emit(true);
this.qualifyingQuestionService.clearQualifyingQuestionSelection();
},
// Error
() => this.router.navigate(['/', 'service-down'])
);
});
}

public searchAndCompleteTask(): void {
// Search Task
const searchParameter = { ccdId: this.caseDetails.case_id } as TaskSearchParameter;
this.searchTasksSubscription = this.workAllocationService.searchTasks(searchParameter)
.subscribe(
(response: any) => {
// Filter task by query id
const filteredTask = response.tasks?.find((task) =>
Object.values(task.additional_properties).some((value) => value === this.queryId)
);
// Trigger event completion
this.eventCompletionParams = {
caseId: this.caseDetails.case_id,
eventId: this.RESPOND_TO_QUERY_EVENT_TRIGGER_ID,
task: filteredTask
};
},
(error) => {
console.error('Error in searchTasksSubscription:', error);
// Handle error appropriately
}
);
private finaliseSubmission(): void {
this.querySubmitted.emit(true);
this.qualifyingQuestionService.clearQualifyingQuestionSelection();
}

private handleError(error: any): void {
console.error('Error in API calls:', error);
this.router.navigate(['/', 'service-down']);
}

private generateCaseQueriesCollectionData(): QmCaseQueriesCollection {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
<ng-container *ngIf="query">
<cut-alert type="error" *ngIf="hasRespondedToQuery()">
<ng-container>{{message}}</ng-container>
</cut-alert>

<br/>
<p>
<p *ngIf="showLink">
<a class="govuk-link" href="javascript:void(0)" (click)="onBack()">{{ 'Back to query list' | rpxTranslate }}</a>
</p>
<div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ActivatedRoute } from '@angular/router';
import { SessionStorageService } from '../../../../../services';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { By } from '@angular/platform-browser';
import { MockRpxTranslatePipe } from '../../../../../test/mock-rpx-translate.pipe';
import { QueryListItem } from '../../models';
import { QueryDetailsComponent } from './query-details.component';
import { Constants } from '../../../../../commons/constants';

describe('QueryDetailsComponent', () => {
let component: QueryDetailsComponent;
Expand Down Expand Up @@ -154,6 +156,14 @@ describe('QueryDetailsComponent', () => {
]
};

const snapshotActivatedRoute = {
snapshot: {
params: {
qid: '123'
}
}
};

beforeEach(async () => {
mockSessionStorageService.getItem.and.returnValue(JSON.stringify(USER));
await TestBed.configureTestingModule({
Expand All @@ -162,7 +172,10 @@ describe('QueryDetailsComponent', () => {
MockRpxTranslatePipe
],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
providers: [{ provide: SessionStorageService, useValue: mockSessionStorageService }]
providers: [
{ provide: SessionStorageService, useValue: mockSessionStorageService },
{ provide: ActivatedRoute, useValue: snapshotActivatedRoute }
]
})
.compileComponents();
});
Expand Down Expand Up @@ -202,6 +215,25 @@ describe('QueryDetailsComponent', () => {
expect(columnHeaders[3].nativeElement.textContent.trim()).toEqual('Attachments');
});

it('should call toggleLinkVisibility when ngOnChanges is called', () => {
spyOn(component, 'toggleLinkVisibility');
component.ngOnChanges();
expect(component.toggleLinkVisibility).toHaveBeenCalled();
});

it('should set showLink to true when user is navigated to follow up to a query', () => {
component.toggleLinkVisibility();
expect(component['queryItemId']).toBe('123');
expect(component.showLink).toBe(true);
});

it('should set showLink to false when user is navigated to response to a query', () => {
component['route'].snapshot.params.qid = '3';
component.ngOnChanges();
component.toggleLinkVisibility();
expect(component.showLink).toBe(false);
});

describe('isCaseworker', () => {
it('should return true if the user doesnt have pui-case-manager', () => {
mockSessionStorageService.getItem.and.returnValue(JSON.stringify(USER));
Expand All @@ -224,4 +256,41 @@ describe('QueryDetailsComponent', () => {
expect(component.isCaseworker()).toBeFalsy();
});
});
describe('hasRespondedToQuery', () => {
it('should emit true and return true if conditions are met', () => {
spyOn(component, 'isCaseworker').and.returnValue(true); // Mock the isCaseworker method to return true
spyOn(component.hasResponded, 'emit');

component.totalNumberOfQueryChildren = 1;

const result = component.hasRespondedToQuery();

expect(component.message).toEqual(Constants.TASK_COMPLETION_ERROR);
expect(component.hasResponded.emit).toHaveBeenCalledWith(true);
expect(result).toBeTruthy();
});

it('should emit false and return false if children length is even', () => {
spyOn(component, 'isCaseworker').and.returnValue(true); // Mock the isCaseworker method to return true
spyOn(component.hasResponded, 'emit'); // Spy on the emit method of hasResponded

const result = component.hasRespondedToQuery();

expect(component.message).toBeUndefined(); // Ensure message is not set
expect(component.hasResponded.emit).toHaveBeenCalledWith(false);
expect(result).toBeFalsy();
});

it('should emit false and return false if query is not defined', () => {
spyOn(component, 'isCaseworker').and.returnValue(true); // Mock the isCaseworker method to return true
spyOn(component.hasResponded, 'emit'); // Spy on the emit method of hasResponded
component.query = null; // Set the query to null

const result = component.hasRespondedToQuery();

expect(component.message).toBeUndefined(); // Ensure message is not set
expect(component.hasResponded.emit).toHaveBeenCalledWith(false);
expect(result).toBeFalsy();
});
});
});
Loading

0 comments on commit 0d01c66

Please sign in to comment.