Skip to content

Commit

Permalink
Start date and end date added to Service Message Banner (#458)
Browse files Browse the repository at this point in the history
* Start date and end date added to Service Message

* version number change

* removed commented lines of code

* removed translation from component

* version number changed

* unit test text changed

* version updated

* error handling message added

* banner message errors modified

* version number amended

* error reworked and unit test

* version change

* AC04 AC05 AC06 and unit test covered

* version number changed

* error bug fix

* version text change

* message error bug fixes

* version change

* reworked greater than dates

* unit test and version update

* Update to release version number

---------

Co-authored-by: RiteshHMCTS <74713687+RiteshHMCTS@users.noreply.github.com>
Co-authored-by: Ritesh Dsouza <ritesh.dsouza@HMCTS.net>
Co-authored-by: Josh <josh.glasgow@hmcts.net>
  • Loading branch information
4 people authored Sep 16, 2024
1 parent 8ae32ef commit 0136a45
Show file tree
Hide file tree
Showing 10 changed files with 302 additions and 38 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@hmcts/rpx-xui-common-lib",
"version": "2.0.28",
"version": "2.0.29",
"engines": {
"node": ">=18.19.0"
},
Expand Down
2 changes: 1 addition & 1 deletion projects/exui-common-lib/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@hmcts/rpx-xui-common-lib",
"version": "2.0.28",
"version": "2.0.29",
"peerDependencies": {
"launchdarkly-js-client-sdk": "^3.3.0",
"ngx-pagination": "^3.2.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

<div class="hmcts-banner__message">
<span class="hmcts-banner__assistive">{{'Warning' | rpxTranslate}}</span>
<h2 class="govuk-heading-s" [innerHTML]="message | rpxTranslate"></h2>
<h2 class="govuk-heading-s" [innerHTML]="message_en"></h2>
<h2 *ngIf="message_cy" class="govuk-heading-s" [innerHTML]="message_cy"></h2>
<a [routerLink]="" class="govuk-link--no-visited-state" (click)="onHideMessageEvent(key)">{{'Hide message' | rpxTranslate}}</a>
</div>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.govuk-link--no-visited-state {
cursor: pointer;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Pipe, PipeTransform } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { ServiceMessageComponent } from './service-message.component';
import { ServiceMessages } from '../../models/service-message.model';

@Pipe({ name: 'rpxTranslate' })
class RpxTranslateMockPipe implements PipeTransform {
Expand Down Expand Up @@ -35,7 +36,14 @@ describe('ServiceMessageComponent', () => {

describe('onHideMessageEvent()', () => {
it('should emit the id of the message to hide', () => {
const hideKey = 'caseworker-probate';
const hideKey: ServiceMessages = {
roles: 'caseworker-probate',
index: 1,
message_en: 'New message',
message_cy: 'Anyyu',
begin: '2024-04-18T00:00:00',
end: '2024-04-19T00:00:00'
};
const hideMessageSpy = spyOn(component.hideMessage, 'emit');
component.onHideMessageEvent(hideKey);
expect(hideMessageSpy).toHaveBeenCalledWith(hideKey);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { ServiceMessages } from '../../models/service-message.model';

@Component({
selector: 'xuilib-service-message',
templateUrl: './service-message.component.html'
templateUrl: './service-message.component.html',
styleUrls: ['./service-message.component.scss']
})
export class ServiceMessageComponent {
@Input() public message: string;
@Input() public key: string;
@Output() public hideMessage = new EventEmitter<string>();
@Input() public message_en: string;
@Input() public message_cy?: string;
@Input() public key: ServiceMessages;
@Output() public hideMessage = new EventEmitter<ServiceMessages>();
constructor() { }

public onHideMessageEvent(key: string) {
public onHideMessageEvent(key: ServiceMessages) {
this.hideMessage.emit(key);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
<div *ngIf="filteredMessages?.size > 0" class="govuk-width-container govuk-!-margin-top-6">
<xuilib-service-message *ngFor="let message of filteredMessages | keyvalue" [key]="message.key"
[message]="message.value | rpxTranslate" (hideMessage)="hideMessage($event)"></xuilib-service-message>
<div *ngIf="isBannerError" class="govuk-width-container govuk-!-margin-top-6">
<div class="hmcts-banner hmcts-banner--warning" *ngFor="let errMsg of bannerErrorMsgs">
<svg class="hmcts-banner__icon" fill="currentColor" role="presentation" focusable="false"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 25 25" height="25" width="25">
<path d="M13.6,15.4h-2.3v-4.5h2.3V15.4z M13.6,19.8h-2.3v-2.2h2.3V19.8z M0,23.2h25L12.5,2L0,23.2z" />
</svg>
<div class="hmcts-banner__message">
<span class="hmcts-banner__assistive">{{'Warning' | rpxTranslate}}</span>
<h2 class="govuk-heading-s">Error:</h2>
<p [innerHTML]="errMsg.message"></p>
</div>
</div>
</div>
<div *ngIf="filteredMessages?.length > 0" class="govuk-width-container govuk-!-margin-top-6">
<xuilib-service-message *ngFor="let message of filteredMessages" [key]="message"
[message_en]="message?.message_en | rpxTranslate"
[message_cy]="message?.message_cy | rpxTranslate"
(hideMessage)="hideMessage($event)">
</xuilib-service-message>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { RpxTranslationConfig, RpxTranslationService } from 'rpx-xui-translation
import { of } from 'rxjs';
import { FeatureToggleService } from '../../services/feature-toggle/feature-toggle.service';
import { ServiceMessagesComponent } from './service-messages.component';
import { ServiceMessages } from '../../models/service-message.model';

@Pipe({ name: 'rpxTranslate' })
class RpxTranslateMockPipe implements PipeTransform {
Expand All @@ -17,14 +18,25 @@ describe('ServiceMessagesComponent', () => {
let fixture: ComponentFixture<ServiceMessagesComponent>;
const mockFeatureToggleService = jasmine.createSpyObj('FeatureToggleService', ['getValue']);

const serviceMessagesFake = {
'caseworker-divorce': 'Divorce users may experience longer loading times than usual in the system.<br />Click <a href="#">here</a> to find out more.',
'caseworker-divorce|caseworker-probate': 'Divorce and probate users may experience longer loading times than usual in the system.<br />Click <a href="#">here</a> to find out more.',
'caseworker-notfound': 'Not found users may experience longer loading times than usual in the system.<br />Click <a href="#">here</a> to find out more.',
'caseworker-probate': 'Probate users may experience longer loading times than usual in the system.<br />Click <a href="#">here</a> to find out more.',
'caseworker-probate|caseworker-withanotherscript': 'Probate and script users may experience longer loading times than usual in the system.<br />Click <a href="#">here</a> to find out more.<scr<script>Ha!</script>ipt> alert("WOW");</script>*',
'caseworker-probate|caseworker-withscript': 'Probate and script users may experience longer loading times than usual in the system.<br />Click <a href="#">here</a> to find out more.<script>alert("security alert");</script>*<link rel=\"stylesheet\" href=\"styles.css\">*'
};
const
serviceMessagesFake: ServiceMessages[] = [
{
roles: 'caseworker-divorce',
index: 2,
message_en: 'Alert services notification',
message_cy: 'Anyyu',
begin: '2024-04-18T00:00:00',
end: '2034-05-19T00:00:00'
},
{
roles: 'caseworker-probate',
index: 3,
message_en: 'Please submit all required forms today ',
message_cy: 'Anyyu',
begin: '2024-04-18T00:00:00',
end: '2044-04-20T00:00:00'
}
];

beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
Expand All @@ -46,26 +58,188 @@ describe('ServiceMessagesComponent', () => {
fixture = TestBed.createComponent(ServiceMessagesComponent);
component = fixture.componentInstance;
component.userRoles = ['caseworker-divorce', 'caseworker-probate'];
component.originalMessages = [];
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});

describe('getServiceMessages()', () => {
describe('call createFilteredMessages on getServiceMessages() call', () => {
it('should get the service messages and filter according to roles', () => {
const serveMsgSpy = spyOn<any>(component, 'createFilteredMessages');
component.getServiceMessages();
expect(component.filteredMessages.size).toBe(5);
expect(serveMsgSpy).toHaveBeenCalled();
});
});
describe('call compareDates on createFilteredMessages call', () => {
it('should get the service messages and filter according to roles', () => {
const dateSpy = spyOn<any>(component, 'compareDates');
component['createFilteredMessages'](serviceMessagesFake);
fixture.autoDetectChanges();
expect(dateSpy).toHaveBeenCalled();
});
});

it('should filter out message if start date is in the future', () => {
const serviceMessagesFake: ServiceMessages[] = [
{
roles: 'caseworker-divorce',
index: 2,
message_en: 'Divorce and probate users may experience longer loading times than usual in the system.<br />Click <a href="#">here</a> to find out more.',
message_cy: 'Anyyu',
begin: '2034-04-18T00:00:00',
end: '2034-05-19T00:00:00'
},
{
roles: 'caseworker-probate',
index: 3,
message_en: 'Maintainance notices',
message_cy: 'Anyyu',
begin: '2024-04-18T00:00:00',
end: '2044-04-20T00:00:00'
}
];
component['createFilteredMessages'](serviceMessagesFake);
fixture.autoDetectChanges();
expect(component.filteredMessages.length).toBe(1);
});

it('should show message when no start date or end date provided', () => {
const serviceMessagesFake: ServiceMessages[] = [
{
roles: 'caseworker-divorce',
index: 2,
message_en: 'Happy birthday.',
message_cy: 'Anyyu',
}
];
component['createFilteredMessages'](serviceMessagesFake);
fixture.autoDetectChanges();
expect(component.filteredMessages.length).toBe(1);
});

it('should show message when no start date provided', () => {
const serviceMessagesFake: ServiceMessages[] = [
{
roles: 'caseworker-divorce',
index: 2,
message_en: 'Happy birthday.',
message_cy: 'Anyyu',
end: '2044-04-20T00:00:00'
}
];
component['createFilteredMessages'](serviceMessagesFake);
fixture.autoDetectChanges();
expect(component.filteredMessages.length).toBe(1);
});

it('should show message when no end date provided', () => {
const serviceMessagesFake: ServiceMessages[] = [
{
roles: 'caseworker-divorce',
index: 12,
message_en: 'Happy birthday.',
message_cy: 'Anyyu',
begin: '2024-04-20T00:00:00'
}
];
component['createFilteredMessages'](serviceMessagesFake);
fixture.autoDetectChanges();
expect(component.filteredMessages.length).toBe(1);
});

it('should filter out message if end date is in the past', () => {
const serviceMessagesFake: ServiceMessages[] = [
{
roles: 'caseworker-divorce',
index: 2,
message_en: 'Services up and running',
message_cy: 'Anyyu',
begin: '2024-03-18T00:00:00',
end: '2024-03-19T00:00:00'
}
];
component['createFilteredMessages'](serviceMessagesFake);
fixture.autoDetectChanges();
expect(component.filteredMessages.length).toBe(0);
});

it('should filter out message if start date is greater than end date', () => {
const serviceMessagesFake: ServiceMessages[] = [
{
roles: 'caseworker-divorce',
index: 8,
message_en: 'Judiciary experience required',
message_cy: 'Anyyu',
begin: '2024-09-03T00:00:00',
end: '2024-08-24T00:00:00'
}
];
component['createFilteredMessages'](serviceMessagesFake);
fixture.autoDetectChanges();
expect(component.filteredMessages.length).toBe(0);
});

it('should filter out message if date format is wrong', () => {
const serviceMessagesFake: ServiceMessages[] = [
{
roles: 'caseworker-divorce',
index: 2,
message_en: 'Date is in WRONG format',
message_cy: 'Anyyu',
begin: '04-04-2024T19:00:00',
end: '2024-04-24T00:00:00'
}
];
component['createFilteredMessages'](serviceMessagesFake);
fixture.autoDetectChanges();
expect(component.filteredMessages.length).toBe(0);
});

describe('hideMessage()', () => {
it('should add an item to the hidden message list', () => {
component.hiddenBanners = [];
const testRole = 'test-message-1';
component.hideMessage(testRole);
component.hideMessage(serviceMessagesFake[0]);
expect((component.hiddenBanners).length).toBe(1);
});
});
});

it('should show error message if start date is greater than the end date', () => {
const serviceMessagesFake: ServiceMessages[] = [
{
roles: 'caseworker-divorce',
index: 2,
message_en: 'Judiciary experience required',
message_cy: 'Anyyu',
begin: '2024-04-25T00:00:00',
end: '2024-04-24T00:00:00'
}
];
component.originalMessages = serviceMessagesFake;
component['compareDates'](serviceMessagesFake[0]);
fixture.detectChanges();
expect(component.isBannerError).toBeTruthy();
expect(component.bannerErrorMsgs).toContain({ message: `The start date is greater than the end date. Message index: ${serviceMessagesFake[0].index}`, index: 2 });
});

it('should show error message if start date or end date is not well formed', () => {
const serviceMessagesFake: ServiceMessages[] = [
{
roles: 'caseworker-divorce',
index: 10,
message_en: 'Malformed start or end date',
message_cy: 'Incorrect date',
begin: '2024-04-25 T00:00:00',
end: '2024-04-24T00:00:00'
}
];
component.originalMessages = serviceMessagesFake;
component['compareDates'](serviceMessagesFake[0]);
fixture.autoDetectChanges();
expect(component.isBannerError).toBeTrue();
expect(component.bannerErrorMsgs.length).toBe(1);
expect(component.bannerErrorMsgs).toContain({ message: `Invalid start date. Message index: ${serviceMessagesFake[0].index}`, index: 10 });
});
});
Loading

0 comments on commit 0136a45

Please sign in to comment.