diff --git a/src/app/shared/live-region/live-region.service.spec.ts b/src/app/shared/live-region/live-region.service.spec.ts index fe5e8b8d8c5..858ef883134 100644 --- a/src/app/shared/live-region/live-region.service.spec.ts +++ b/src/app/shared/live-region/live-region.service.spec.ts @@ -1,12 +1,14 @@ import { LiveRegionService } from './live-region.service'; import { fakeAsync, tick, flush } from '@angular/core/testing'; +import { UUIDService } from '../../core/shared/uuid.service'; describe('liveRegionService', () => { let service: LiveRegionService; - beforeEach(() => { - service = new LiveRegionService(); + service = new LiveRegionService( + new UUIDService(), + ); }); describe('addMessage', () => { @@ -85,6 +87,34 @@ describe('liveRegionService', () => { expect(results[3]).toEqual([]); })); + it('should not pop messages added after clearing within timeOut period', fakeAsync(() => { + const results: string[][] = []; + + service.getMessages$().subscribe((messages) => { + results.push(messages); + }); + + expect(results.length).toEqual(1); + expect(results[0]).toEqual([]); + + service.addMessage('Message One'); + tick(10000); + service.clear(); + tick(15000); + service.addMessage('Message Two'); + + // Message Two should not be cleared after 5 more seconds + tick(5000); + + expect(results.length).toEqual(4); + expect(results[3]).toEqual(['Message Two']); + + // But should be cleared 30 seconds after it was added + tick(25000); + expect(results.length).toEqual(5); + expect(results[4]).toEqual([]); + })); + it('should respect configured timeOut', fakeAsync(() => { const results: string[][] = []; diff --git a/src/app/shared/live-region/live-region.service.ts b/src/app/shared/live-region/live-region.service.ts index 482d1ca1bbf..d89d72a9675 100644 --- a/src/app/shared/live-region/live-region.service.ts +++ b/src/app/shared/live-region/live-region.service.ts @@ -1,12 +1,18 @@ import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import { environment } from '../../../environments/environment'; +import { UUIDService } from '../../core/shared/uuid.service'; @Injectable({ providedIn: 'root', }) export class LiveRegionService { + constructor( + protected uuidService: UUIDService, + ) { + } + /** * The duration after which the messages disappear in milliseconds * @protected @@ -14,10 +20,11 @@ export class LiveRegionService { protected messageTimeOutDurationMs: number = environment.liveRegion.messageTimeOutDurationMs; /** - * Array containing the messages that should be shown in the live region + * Array containing the messages that should be shown in the live region, + * together with a uuid, so they can be uniquely identified * @protected */ - protected messages: string[] = []; + protected messages: { message: string, uuid: string }[] = []; /** * BehaviorSubject emitting the array with messages every time the array updates @@ -34,27 +41,28 @@ export class LiveRegionService { /** * Returns a copy of the array with the current live region messages */ - getMessages() { - return [...this.messages]; + getMessages(): string[] { + return this.messages.map(messageObj => messageObj.message); } /** * Returns the BehaviorSubject emitting the array with messages every time the array updates */ - getMessages$() { + getMessages$(): BehaviorSubject { return this.messages$; } /** * Adds a message to the live-region messages array * @param message + * @return The uuid of the message */ - addMessage(message: string) { - this.messages.push(message); + addMessage(message: string): string { + const uuid = this.uuidService.generate(); + this.messages.push({ message, uuid }); + setTimeout(() => this.clearMessageByUUID(uuid), this.messageTimeOutDurationMs); this.emitCurrentMessages(); - - // Clear the message once the timeOut has passed - setTimeout(() => this.pop(), this.messageTimeOutDurationMs); + return uuid; } /** @@ -66,12 +74,15 @@ export class LiveRegionService { } /** - * Removes the longest living message from the array. + * Removes the message with the given UUID from the messages array + * @param uuid The uuid of the message to clear * @protected */ - protected pop() { - if (this.messages.length > 0) { - this.messages.shift(); + clearMessageByUUID(uuid: string) { + const index = this.messages.findIndex(messageObj => messageObj.uuid === uuid); + + if (index !== -1) { + this.messages.splice(index, 1); this.emitCurrentMessages(); } }