From 460f7cb1dc6033c98e6142a721d63b27c810403c Mon Sep 17 00:00:00 2001 From: "kim.tran" Date: Wed, 7 Feb 2024 11:28:19 +0100 Subject: [PATCH 1/4] feat: mock for message service --- .../mocks/app-state-service-mock.ts | 32 +++-------- .../mocks/fake-topic.ts | 32 +++++++++++ .../portal-integration-angular/mocks/index.ts | 3 +- .../mocks/portal-message-service-mock.ts | 54 +++++++++++++++++++ .../lib/services/portal-message.service.ts | 2 +- 5 files changed, 95 insertions(+), 28 deletions(-) create mode 100644 libs/portal-integration-angular/mocks/fake-topic.ts create mode 100644 libs/portal-integration-angular/mocks/portal-message-service-mock.ts diff --git a/libs/portal-integration-angular/mocks/app-state-service-mock.ts b/libs/portal-integration-angular/mocks/app-state-service-mock.ts index 6beec84a..2ef6bcb9 100644 --- a/libs/portal-integration-angular/mocks/app-state-service-mock.ts +++ b/libs/portal-integration-angular/mocks/app-state-service-mock.ts @@ -1,38 +1,18 @@ import { Injectable } from '@angular/core' import { PageInfo, Portal } from '@onecx/integration-interface' -import { BehaviorSubject, Observable, Observer, Subscription, UnaryFunction } from 'rxjs' +import { AppStateService } from '../src/lib/services/app-state.service' +import { FakeTopic } from './fake-topic' -class FakeTopic { - private state = new BehaviorSubject(this.initialValue) - constructor(private initialValue: T) {} - asObservable(): Observable { - return this.state.asObservable() - } - - subscribe( - observerOrNext?: Partial> | ((value: T) => void), - error?: (error: any) => void, - complete?: () => void - ): Subscription { - return (this.asObservable()).subscribe(observerOrNext, error, complete) - } - - pipe(...operations: UnaryFunction[]): unknown { - return (this.asObservable()).pipe(...operations) - } - - publish(value: T): Promise { - this.state.next(value) - return Promise.resolve() - } +export function provideAppServiceMock() { + return [{ provide: AppStateService, useClass: AppStateServiceMock }] } @Injectable() export class AppStateServiceMock { - globalError$ = new FakeTopic('') + globalError$ = new FakeTopic() globalLoading$ = new FakeTopic(false) currentMfe$ = new FakeTopic({ mountPath: '/', remoteBaseUrl: '.', baseHref: '/', shellName: 'test' }) currentPage$ = new FakeTopic(undefined) currentPortal$ = new FakeTopic({ baseUrl: '/', microfrontendRegistrations: [], portalName: 'Test portal' }) - isAuthenticated$ = new FakeTopic(undefined) + isAuthenticated$ = new FakeTopic(null) } diff --git a/libs/portal-integration-angular/mocks/fake-topic.ts b/libs/portal-integration-angular/mocks/fake-topic.ts new file mode 100644 index 00000000..d1f5c446 --- /dev/null +++ b/libs/portal-integration-angular/mocks/fake-topic.ts @@ -0,0 +1,32 @@ +import { Subject, Observable, Observer, Subscription, UnaryFunction, BehaviorSubject, ReplaySubject } from 'rxjs' + +export class FakeTopic { + private state: Subject + constructor(initialValue: T | undefined = undefined) { + if (initialValue !== undefined) { + this.state = new BehaviorSubject(initialValue) + } else { + this.state = new ReplaySubject(1) + } + } + asObservable(): Observable { + return this.state.asObservable() + } + + subscribe( + observerOrNext?: Partial> | ((value: T) => void), + error?: (error: any) => void, + complete?: () => void + ): Subscription { + return (this.asObservable()).subscribe(observerOrNext, error, complete) + } + + pipe(...operations: UnaryFunction[]): unknown { + return (this.asObservable()).pipe(...operations) + } + + publish(value: T): Promise { + this.state.next(value) + return Promise.resolve() + } +} diff --git a/libs/portal-integration-angular/mocks/index.ts b/libs/portal-integration-angular/mocks/index.ts index 0d90321d..3e84d030 100644 --- a/libs/portal-integration-angular/mocks/index.ts +++ b/libs/portal-integration-angular/mocks/index.ts @@ -1 +1,2 @@ -export * from './app-state-service-mock' \ No newline at end of file +export * from './app-state-service-mock' +export * from './portal-message-service-mock' \ No newline at end of file diff --git a/libs/portal-integration-angular/mocks/portal-message-service-mock.ts b/libs/portal-integration-angular/mocks/portal-message-service-mock.ts new file mode 100644 index 00000000..3811e294 --- /dev/null +++ b/libs/portal-integration-angular/mocks/portal-message-service-mock.ts @@ -0,0 +1,54 @@ +import { Injectable } from '@angular/core' +import { TranslateService } from '@ngx-translate/core' +import { combineLatest, of } from 'rxjs' +import { Message, PortalMessageService } from '../src/lib/services/portal-message.service' +import { FakeTopic } from './fake-topic' +import { Message as TopicMessage } from '@onecx/integration-interface' + +export function providePortalMessageServiceMock() { + return [ + { provide: PortalMessageServiceMock, useClass: PortalMessageServiceMock }, + { provide: PortalMessageService, useExisting: PortalMessageServiceMock }, + ] +} + +@Injectable() +export class PortalMessageServiceMock { + constructor(private translateService: TranslateService) {} + lastMessages: { type: 'success' | 'info' | 'error' | 'warning'; value: Message }[] = [] + message$ = new FakeTopic() + + success(msg: Message) { + this.lastMessages.push({ type: 'success', value: msg }) + this.addTranslated('success', msg) + } + + info(msg: Message) { + this.lastMessages.push({ type: 'info', value: msg }) + this.addTranslated('info', msg) + } + + error(msg: Message) { + this.lastMessages.push({ type: 'error', value: msg }) + this.addTranslated('error', msg) + } + + warning(msg: Message) { + this.lastMessages.push({ type: 'warning', value: msg }) + this.addTranslated('warning', msg) + } + + private addTranslated(severity: string, msg: Message) { + combineLatest([ + msg.summaryKey ? this.translateService.get(msg.summaryKey || '', msg.summaryParameters) : of(undefined), + msg.detailKey ? this.translateService.get(msg.detailKey, msg.detailParameters) : of(undefined), + ]).subscribe(([summaryTranslation, detailTranslation]: string[]) => { + this.message$.publish({ + ...msg, + severity: severity, + summary: summaryTranslation, + detail: detailTranslation, + }) + }) + } +} diff --git a/libs/portal-integration-angular/src/lib/services/portal-message.service.ts b/libs/portal-integration-angular/src/lib/services/portal-message.service.ts index 9b6ddc25..ac3bf25d 100644 --- a/libs/portal-integration-angular/src/lib/services/portal-message.service.ts +++ b/libs/portal-integration-angular/src/lib/services/portal-message.service.ts @@ -3,7 +3,7 @@ import { TranslateService } from '@ngx-translate/core' import { MessageTopic } from '@onecx/integration-interface' import { combineLatest, of } from 'rxjs' -type Message = { +export type Message = { summaryKey?: string summaryParameters?: object detailKey?: string From ce2bcc80e55fcca9a700578d47dfc78dfe25641d Mon Sep 17 00:00:00 2001 From: "kim.tran" Date: Wed, 7 Feb 2024 11:39:05 +0100 Subject: [PATCH 2/4] fix: imports in mocks --- libs/portal-integration-angular/mocks/app-state-service-mock.ts | 2 +- .../mocks/portal-message-service-mock.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/portal-integration-angular/mocks/app-state-service-mock.ts b/libs/portal-integration-angular/mocks/app-state-service-mock.ts index 2ef6bcb9..033bf6e4 100644 --- a/libs/portal-integration-angular/mocks/app-state-service-mock.ts +++ b/libs/portal-integration-angular/mocks/app-state-service-mock.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core' import { PageInfo, Portal } from '@onecx/integration-interface' -import { AppStateService } from '../src/lib/services/app-state.service' +import { AppStateService } from '@onecx/portal-integration-angular' import { FakeTopic } from './fake-topic' export function provideAppServiceMock() { diff --git a/libs/portal-integration-angular/mocks/portal-message-service-mock.ts b/libs/portal-integration-angular/mocks/portal-message-service-mock.ts index 3811e294..16dd165a 100644 --- a/libs/portal-integration-angular/mocks/portal-message-service-mock.ts +++ b/libs/portal-integration-angular/mocks/portal-message-service-mock.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core' import { TranslateService } from '@ngx-translate/core' import { combineLatest, of } from 'rxjs' -import { Message, PortalMessageService } from '../src/lib/services/portal-message.service' +import { Message, PortalMessageService } from '@onecx/portal-integration-angular' import { FakeTopic } from './fake-topic' import { Message as TopicMessage } from '@onecx/integration-interface' From 6b28ff36084b5cab022bfb7df935b81389e2722d Mon Sep 17 00:00:00 2001 From: "kim.tran" Date: Wed, 7 Feb 2024 12:36:13 +0100 Subject: [PATCH 3/4] fix: ignore eslint rule next line nx/enforce-module-boundaries --- libs/portal-integration-angular/mocks/app-state-service-mock.ts | 1 + .../mocks/portal-message-service-mock.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/libs/portal-integration-angular/mocks/app-state-service-mock.ts b/libs/portal-integration-angular/mocks/app-state-service-mock.ts index 033bf6e4..9a70c83a 100644 --- a/libs/portal-integration-angular/mocks/app-state-service-mock.ts +++ b/libs/portal-integration-angular/mocks/app-state-service-mock.ts @@ -1,5 +1,6 @@ import { Injectable } from '@angular/core' import { PageInfo, Portal } from '@onecx/integration-interface' +// eslint-disable-next-line import { AppStateService } from '@onecx/portal-integration-angular' import { FakeTopic } from './fake-topic' diff --git a/libs/portal-integration-angular/mocks/portal-message-service-mock.ts b/libs/portal-integration-angular/mocks/portal-message-service-mock.ts index 16dd165a..563d1220 100644 --- a/libs/portal-integration-angular/mocks/portal-message-service-mock.ts +++ b/libs/portal-integration-angular/mocks/portal-message-service-mock.ts @@ -1,6 +1,7 @@ import { Injectable } from '@angular/core' import { TranslateService } from '@ngx-translate/core' import { combineLatest, of } from 'rxjs' +// eslint-disable-next-line import { Message, PortalMessageService } from '@onecx/portal-integration-angular' import { FakeTopic } from './fake-topic' import { Message as TopicMessage } from '@onecx/integration-interface' From 0e47e710b91cd60a20f12c37a2822ef1b80e708e Mon Sep 17 00:00:00 2001 From: "kim.tran" Date: Thu, 8 Feb 2024 09:57:24 +0100 Subject: [PATCH 4/4] fix: mock does not necessarily need TranslationModule to be provided --- .../mocks/portal-message-service-mock.ts | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/libs/portal-integration-angular/mocks/portal-message-service-mock.ts b/libs/portal-integration-angular/mocks/portal-message-service-mock.ts index 563d1220..1630c1f3 100644 --- a/libs/portal-integration-angular/mocks/portal-message-service-mock.ts +++ b/libs/portal-integration-angular/mocks/portal-message-service-mock.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core' +import { Injectable, Optional } from '@angular/core' import { TranslateService } from '@ngx-translate/core' import { combineLatest, of } from 'rxjs' // eslint-disable-next-line @@ -15,7 +15,7 @@ export function providePortalMessageServiceMock() { @Injectable() export class PortalMessageServiceMock { - constructor(private translateService: TranslateService) {} + constructor(@Optional() private translateService?: TranslateService) {} lastMessages: { type: 'success' | 'info' | 'error' | 'warning'; value: Message }[] = [] message$ = new FakeTopic() @@ -40,16 +40,20 @@ export class PortalMessageServiceMock { } private addTranslated(severity: string, msg: Message) { - combineLatest([ - msg.summaryKey ? this.translateService.get(msg.summaryKey || '', msg.summaryParameters) : of(undefined), - msg.detailKey ? this.translateService.get(msg.detailKey, msg.detailParameters) : of(undefined), - ]).subscribe(([summaryTranslation, detailTranslation]: string[]) => { - this.message$.publish({ - ...msg, - severity: severity, - summary: summaryTranslation, - detail: detailTranslation, + if (this.translateService) { + combineLatest([ + msg.summaryKey ? this.translateService.get(msg.summaryKey || '', msg.summaryParameters) : of(undefined), + msg.detailKey ? this.translateService.get(msg.detailKey, msg.detailParameters) : of(undefined), + ]).subscribe(([summaryTranslation, detailTranslation]: string[]) => { + this.message$.publish({ + ...msg, + severity: severity, + summary: summaryTranslation, + detail: detailTranslation, + }) }) - }) + } else { + console.log('TranslationModule not imported in TestBed. Therefore message$ is not updated.') + } } }