Skip to content

Commit

Permalink
Exui 2729 callback error (#4211)
Browse files Browse the repository at this point in the history
* fix callback error handler

* Update query-management-container.component.ts

* test added

* error border color updated, loading service added

* code tidy

* code tidy

* toolkit version updated along with cve

---------

Co-authored-by: RiteshHMCTS <[email protected]>
Co-authored-by: Ritesh Dsouza <[email protected]>
  • Loading branch information
3 people authored Jan 28, 2025
1 parent 32f5b53 commit 38796d1
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 25 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
"@cucumber/cucumber": "^10.8.0",
"@edium/fsm": "^2.1.2",
"@faker-js/faker": "^9.2.0",
"@hmcts/ccd-case-ui-toolkit": "7.1.31",
"@hmcts/ccd-case-ui-toolkit": "7.1.32",
"@hmcts/ccpay-web-component": "6.2.1",
"@hmcts/frontend": "0.0.50-alpha",
"@hmcts/media-viewer": "4.0.10",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<exui-app-header></exui-app-header>

<div class="govuk-width-container">
<xuilib-loading-spinner *ngIf="showSpinner$ | async"></xuilib-loading-spinner>
<div class="govuk-width-container query-container">
<main class="govuk-main-wrapper" id="main-content" role="main">
<!-- Error message summary -->
<div *ngIf="errorMessages.length > 0" class="govuk-error-summary"
Expand All @@ -20,6 +20,15 @@ <h2 class="govuk-error-summary__title" id="error-summary-title">
</div>
</div>

<exui-alert></exui-alert>

<ccd-callback-errors
[triggerTextContinue]="triggerTextStart"
[triggerTextIgnore]="triggerTextIgnoreWarnings"
[callbackErrorsSubject]="callbackErrorsSubject"
(callbackErrorsContext)="callbackErrorsNotify($event)">
</ccd-callback-errors>

<!-- Query management workflow pages -->
<ng-container *ngIf="!showSummary && !showConfirmation" [formGroup]="formGroup">
<ng-container [ngSwitch]="queryCreateContext">
Expand All @@ -34,18 +43,20 @@ <h2 class="govuk-error-summary__title" id="error-summary-title">
<ccd-query-write-raise-query *ngSwitchCase="queryCreateContextEnum.NEW_QUERY"
[formGroup]="formGroup"
[caseDetails]="caseDetails"
[showForm]="showForm"
[queryCreateContext]="queryCreateContext" [submitted]="submitted">
</ccd-query-write-raise-query>
<ccd-query-write-respond-to-query
*ngSwitchCase="[queryCreateContextEnum.RESPOND, queryCreateContextEnum.FOLLOWUP].includes(queryCreateContext) ? queryCreateContext : !queryCreateContext"
[queryItem]="queryItem" [formGroup]="formGroup"
[showForm]="showForm"
[submitted]="submitted" [queryCreateContext]="queryCreateContext">
</ccd-query-write-respond-to-query>
</div>
</ng-container>

<div class="query-form-container"
*ngIf="queryCreateContext !== queryCreateContextEnum.NEW_QUERY_QUALIFYING_QUESTION_OPTIONS && queryCreateContext !== queryCreateContextEnum.NEW_QUERY_QUALIFYING_QUESTION_DETAIL">
*ngIf="showForm && queryCreateContext !== queryCreateContextEnum.NEW_QUERY_QUALIFYING_QUESTION_OPTIONS && queryCreateContext !== queryCreateContextEnum.NEW_QUERY_QUALIFYING_QUESTION_DETAIL">
<div class="govuk-form-group" [class.govuk-form-group--error]="formGroup.get('attachments')?.errors?.length">
<ccd-query-write-add-documents [formGroup]="formGroup"
[label]="'Add document to this query' | rpxTranslate"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import {
QualifyingQuestionsErrorMessage,
QueryCreateContext,
QueryWriteRaiseQueryComponent,
ErrorNotifierService,
AlertService,
QueryWriteRespondToQueryComponent
} from '@hmcts/ccd-case-ui-toolkit';
import { FeatureToggleService } from '@hmcts/rpx-xui-common-lib';
import { FeatureToggleService, LoadingService } from '@hmcts/rpx-xui-common-lib';
import { provideMockStore } from '@ngrx/store/testing';
import { BehaviorSubject, of, throwError } from 'rxjs';
import { RaiseQueryErrorMessage } from '../../models/raise-query-error-message.enum';
Expand Down Expand Up @@ -169,6 +171,8 @@ describe('QueryManagementContainerComponent', () => {
}
];

const mockAlertService = jasmine.createSpyObj('alertService', ['error']);
const mockErrorNotifierService = jasmine.createSpyObj('ErrorNotifierService', ['announceError']);
const casesService = jasmine.createSpyObj('casesService', ['caseView', 'getEventTrigger', 'createEvent', 'getCaseViewV2', 'cachedCaseView']);
const qualifyingQuestionService = jasmine.createSpyObj('qualifyingQuestionService', ['setQualifyingQuestionSelection', 'clearQualifyingQuestionSelection']);
const mockCaseNotifier = new CaseNotifier(casesService);
Expand Down Expand Up @@ -216,7 +220,10 @@ describe('QueryManagementContainerComponent', () => {
{ provide: Router, useValue: mockRouter },
{ provide: Location, useValue: locationMock },
{ provide: CaseNotifier, useValue: mockCaseNotifier },
{ provide: FeatureToggleService, useValue: mockFeatureToggleService }
{ provide: FeatureToggleService, useValue: mockFeatureToggleService },
{ provide: ErrorNotifierService, useValue: mockErrorNotifierService },
{ provide: AlertService, useValue: mockAlertService },
LoadingService
]
}).compileComponents();
}));
Expand Down Expand Up @@ -694,8 +701,7 @@ describe('QueryManagementContainerComponent', () => {
describe('getEventTrigger', () => {
it('should handle error correctly when getEventTrigger fails', () => {
// Mock the service to return an error
const errorMock = new Error('Network error');
casesService.getEventTrigger.and.returnValue(throwError(() => errorMock));
casesService.getEventTrigger.and.returnValue(throwError(() => ({ status: 401 })));

component.queryCreateContext = QueryCreateContext.NEW_QUERY;
// eslint-disable-next-line dot-notation
Expand All @@ -711,6 +717,19 @@ describe('QueryManagementContainerComponent', () => {
fieldId: 'evenDataError'
});
});

it('should handle error', () => {
// Mock the service to return an error
const error = new Error('Network error');
casesService.getEventTrigger.and.returnValue(throwError(() => error));

component.queryCreateContext = QueryCreateContext.NEW_QUERY;
// eslint-disable-next-line dot-notation
component['getEventTrigger']();

expect(mockErrorNotifierService.announceError).toHaveBeenCalledWith(error);
expect(mockAlertService.error).toHaveBeenCalledWith({ phrase: error.message });
});
});
});

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Location } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import {
Expand All @@ -13,24 +13,28 @@ import {
CasesService,
CaseEventTrigger,
CaseField,
QualifyingQuestionService
QualifyingQuestionService,
ErrorNotifierService,
AlertService,
CallbackErrorsContext,
HttpError
} from '@hmcts/ccd-case-ui-toolkit';
import { FeatureToggleService } from '@hmcts/rpx-xui-common-lib';
import { FeatureToggleService, LoadingService } from '@hmcts/rpx-xui-common-lib';
import { map, take } from 'rxjs/operators';
import { ErrorMessage } from '../../../app/models';
import { CaseTypeQualifyingQuestions } from '../../models/qualifying-questions/casetype-qualifying-questions.model';
import { QualifyingQuestion } from '../../models/qualifying-questions/qualifying-question.model';
import { RaiseQueryErrorMessage } from '../../models/raise-query-error-message.enum';
import { select, Store } from '@ngrx/store';
import * as fromRoot from '../../../app/store';
import { combineLatest, Observable } from 'rxjs';
import { combineLatest, Observable, Subject } from 'rxjs';

@Component({
selector: 'exui-query-management-container',
templateUrl: './query-management-container.component.html',
styleUrls: ['./query-management-container.component.scss']
})
export class QueryManagementContainerComponent implements OnInit {
export class QueryManagementContainerComponent implements OnInit, OnDestroy {
private readonly LD_QUALIFYING_QUESTIONS = 'qm-qualifying-questions';
private readonly RAISE_A_QUERY_NAME = 'Raise a new query';
public static readonly RAISE_A_QUERY_QUESTION_OPTION = 'raiseAQuery';
Expand All @@ -46,6 +50,9 @@ export class QueryManagementContainerComponent implements OnInit {
public static readonly FIELD_TYPE_COLLECTION = 'Collection';
public static readonly FIELD_TYPE_COMPLEX = 'Complex';

public static readonly TRIGGER_TEXT_CONTINUE = 'Ignore Warning and Continue';
public static readonly TRIGGER_TEXT_START = 'Continue';

private queryItemId: string;
public caseId: string;
public queryCreateContext: QueryCreateContext;
Expand All @@ -70,6 +77,15 @@ export class QueryManagementContainerComponent implements OnInit {
public eventTrigger: CaseEventTrigger;
public eventData: CaseEventTrigger;
public showContinueButton: boolean = true;
public showForm: boolean;

public triggerTextStart = QueryManagementContainerComponent.TRIGGER_TEXT_START;
public triggerTextIgnoreWarnings = QueryManagementContainerComponent.TRIGGER_TEXT_CONTINUE;
public triggerText: string;
public ignoreWarning: boolean;

public callbackErrorsSubject: Subject<any> = new Subject();
public showSpinner$: Observable<boolean>;

constructor(
private readonly activatedRoute: ActivatedRoute,
Expand All @@ -79,7 +95,10 @@ export class QueryManagementContainerComponent implements OnInit {
private readonly featureToggleService: FeatureToggleService,
private readonly casesService: CasesService,
private readonly store: Store<fromRoot.State>,
private readonly qualifyingQuestionService: QualifyingQuestionService
private readonly qualifyingQuestionService: QualifyingQuestionService,
private readonly errorNotifierService: ErrorNotifierService,
private readonly alertService: AlertService,
private readonly loadingService: LoadingService
) {}

public ngOnInit(): void {
Expand All @@ -88,6 +107,7 @@ export class QueryManagementContainerComponent implements OnInit {
this.queryCreateContext = this.getQueryCreateContext();
this.qualifyingQuestions$ = this.getQualifyingQuestions();
this.qualifyingQuestionsControl = new FormControl(null, Validators.required);
this.showSpinner$ = this.loadingService.isLoading as any;

this.formGroup = new FormGroup({
subject: new FormControl(null),
Expand All @@ -111,6 +131,20 @@ export class QueryManagementContainerComponent implements OnInit {
}
}

public callbackErrorsNotify(errorContext: CallbackErrorsContext) {
this.ignoreWarning = errorContext.ignoreWarning;
}

ngOnDestroy(): void {
this.unsubscribe(this.callbackErrorsSubject);
}

public unsubscribe(subscription: any) {
if (subscription) {
subscription.unsubscribe();
}
}

public showResponseForm(): void {
this.showSummary = false;
}
Expand Down Expand Up @@ -327,6 +361,7 @@ export class QueryManagementContainerComponent implements OnInit {
}

private getEventTrigger():void {
const loadingToken = this.loadingService.register();
this.caseNotifier.caseView.pipe(take(1)).subscribe((caseDetails) => {
this.caseDetails = caseDetails;

Expand All @@ -339,6 +374,8 @@ export class QueryManagementContainerComponent implements OnInit {
this.eventTrigger$.subscribe({
next: (eventTrigger) => {
this.eventTrigger = eventTrigger;
this.showForm = true;
this.loadingService.unregister(loadingToken);

if (this.queryCreateContext === QueryCreateContext.NEW_QUERY){
this.caseQueriesCollectionsCount();
Expand All @@ -348,10 +385,22 @@ export class QueryManagementContainerComponent implements OnInit {
this.processFilteredMessages();
}
},
error: (err) => {
console.error('Error occurred while fetching event data:', err);
this.eventDataError = true;
this.addError('Something unexpected happened. please try again later.', 'evenDataError');
error: (err: HttpError) => {
this.loadingService.unregister(loadingToken);
if (err.status !== 401 && err.status !== 403) {
this.errorNotifierService.announceError(err);
this.alertService.error({ phrase: err.message });
console.error('Error occurred while fetching event data:', err);
this.callbackErrorsSubject.next(err);
if (!this.ignoreWarning) {
this.showContinueButton = false;
} else {
this.showForm = true;
}
} else {
this.eventDataError = true;
this.addError('Something unexpected happened. please try again later.', 'evenDataError');
}
window.scrollTo({ left: 0, top: 0, behavior: 'smooth' });
}
});
Expand Down
12 changes: 12 additions & 0 deletions src/style/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -467,3 +467,15 @@ button:focus {
background-color: #ffdd00 !important;
}
}


/** Error Summary
* Make border color consistent with other error messages for HMCTS
*/
.query-container .error-summary {
border-color: #d4351c;

&:focus {
outline: none;
}
}
2 changes: 0 additions & 2 deletions yarn-audit-known-issues
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
{"value":"domexception","children":{"ID":"domexception (deprecation)","Issue":"Use your platform's native DOMException instead","Severity":"moderate","Vulnerable Versions":"4.0.0","Tree Versions":["4.0.0"],"Dependents":["jsdom@virtual:145e7af5a4eef7edc3b5342155c9759e46fd272a65da8c54e71e3a726711ad979907e1887a3fdcf00ecab676547214a60ab3eeb7f8437d187eab031c26d7a1bb#npm:20.0.3"]}}
{"value":"follow-redirects","children":{"ID":1096353,"Issue":"Follow Redirects improperly handles URLs in the url.parse() function","URL":"https://github.com/advisories/GHSA-jchw-25xp-jwwc","Severity":"moderate","Vulnerable Versions":"<1.15.4","Tree Versions":["1.15.2"],"Dependents":["http-proxy@npm:1.18.1"]}}
{"value":"follow-redirects","children":{"ID":1096856,"Issue":"follow-redirects' Proxy-Authorization header kept across hosts","URL":"https://github.com/advisories/GHSA-cxjh-pqwp-8mfp","Severity":"moderate","Vulnerable Versions":"<=1.15.5","Tree Versions":["1.15.2"],"Dependents":["http-proxy@npm:1.18.1"]}}
{"value":"formidable","children":{"ID":"formidable (deprecation)","Issue":"Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau","Severity":"moderate","Vulnerable Versions":"1.2.6","Tree Versions":["1.2.6"],"Dependents":["superagent@npm:5.3.1"]}}
{"value":"fstream","children":{"ID":"fstream (deprecation)","Issue":"This package is no longer supported.","Severity":"moderate","Vulnerable Versions":"1.0.12","Tree Versions":["1.0.12"],"Dependents":["unzipper@npm:0.10.14"]}}
{"value":"gauge","children":{"ID":"gauge (deprecation)","Issue":"This package is no longer supported.","Severity":"moderate","Vulnerable Versions":"4.0.4","Tree Versions":["4.0.4"],"Dependents":["npmlog@npm:6.0.2"]}}
{"value":"glob","children":{"ID":"glob (deprecation)","Issue":"Glob versions prior to v9 are no longer supported","Severity":"moderate","Vulnerable Versions":"7.2.3","Tree Versions":["7.2.3"],"Dependents":["shelljs@npm:0.8.5"]}}
Expand All @@ -37,7 +36,6 @@
{"value":"semver","children":{"ID":1101088,"Issue":"semver vulnerable to Regular Expression Denial of Service","URL":"https://github.com/advisories/GHSA-c2qf-rxjj-qqgw","Severity":"high","Vulnerable Versions":">=7.0.0 <7.5.2","Tree Versions":["7.3.7"],"Dependents":["global-agent@npm:2.2.0"]}}
{"value":"semver","children":{"ID":1101090,"Issue":"semver vulnerable to Regular Expression Denial of Service","URL":"https://github.com/advisories/GHSA-c2qf-rxjj-qqgw","Severity":"high","Vulnerable Versions":">=6.0.0 <6.3.1","Tree Versions":["6.3.0"],"Dependents":["istanbul-lib-instrument@npm:5.2.1"]}}
{"value":"shortid","children":{"ID":"shortid (deprecation)","Issue":"Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.","Severity":"moderate","Vulnerable Versions":"2.2.16","Tree Versions":["2.2.16"],"Dependents":["rpx-exui@workspace:."]}}
{"value":"superagent","children":{"ID":"superagent (deprecation)","Issue":"Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net","Severity":"moderate","Vulnerable Versions":"5.3.1","Tree Versions":["5.3.1"],"Dependents":["@hmcts/nodejs-healthcheck@npm:1.7.0"]}}
{"value":"tar","children":{"ID":1097493,"Issue":"Denial of service while parsing a tar file due to lack of folders count validation","URL":"https://github.com/advisories/GHSA-f5x3-32g6-xq36","Severity":"moderate","Vulnerable Versions":"<6.2.1","Tree Versions":["6.2.0"],"Dependents":["node-gyp@npm:9.4.0"]}}
{"value":"tough-cookie","children":{"ID":1097682,"Issue":"tough-cookie Prototype Pollution vulnerability","URL":"https://github.com/advisories/GHSA-72xf-g2v4-qvf3","Severity":"moderate","Vulnerable Versions":"<4.1.3","Tree Versions":["2.5.0"],"Dependents":["request@npm:2.88.2"]}}
{"value":"uuid","children":{"ID":"uuid (deprecation)","Issue":"Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.","Severity":"moderate","Vulnerable Versions":"3.4.0","Tree Versions":["3.4.0"],"Dependents":["launchdarkly-js-sdk-common@npm:3.8.2"]}}
Expand Down
10 changes: 5 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3455,12 +3455,12 @@ __metadata:
languageName: node
linkType: hard

"@hmcts/ccd-case-ui-toolkit@npm:7.1.31":
version: 7.1.31
resolution: "@hmcts/ccd-case-ui-toolkit@npm:7.1.31"
"@hmcts/ccd-case-ui-toolkit@npm:7.1.32":
version: 7.1.32
resolution: "@hmcts/ccd-case-ui-toolkit@npm:7.1.32"
dependencies:
tslib: "npm:^2.3.0"
checksum: 10/38b65a737dcc1daeb04baf9eed8667810be40b766907557b6c0a067255b1752b274e6e94da2ededf15e1b89a25e0790c53f49a32b119df342ddb8b1283b678a8
checksum: 10/14449020dca2e95758fd9f742f4d8151be50388c65ea5df66b7664423421f019ffe8dd151232c0fce7cb68a23096bec6e5e11370c33fe2e85d8ebd38ff479270
languageName: node
linkType: hard

Expand Down Expand Up @@ -22308,7 +22308,7 @@ __metadata:
"@cucumber/cucumber": "npm:^10.8.0"
"@edium/fsm": "npm:^2.1.2"
"@faker-js/faker": "npm:^9.2.0"
"@hmcts/ccd-case-ui-toolkit": "npm:7.1.31"
"@hmcts/ccd-case-ui-toolkit": "npm:7.1.32"
"@hmcts/ccpay-web-component": "npm:6.2.1"
"@hmcts/frontend": "npm:0.0.50-alpha"
"@hmcts/media-viewer": "npm:4.0.10"
Expand Down

0 comments on commit 38796d1

Please sign in to comment.