diff --git a/goofy-client/libs/navigation/src/lib/header-container/header-container.component.ts b/goofy-client/libs/navigation/src/lib/header-container/header-container.component.ts index 1ac12eadeda9850e6c1a9ac4f24b74114a2b91ac..7a884f0c64b6e6edaf5217ecdde397855f65f69b 100644 --- a/goofy-client/libs/navigation/src/lib/header-container/header-container.component.ts +++ b/goofy-client/libs/navigation/src/lib/header-container/header-container.component.ts @@ -9,7 +9,6 @@ import { Observable } from 'rxjs'; styleUrls: ['./header-container.component.scss'] }) export class HeaderContainerComponent { - navigationCollapse$: Observable<boolean>; constructor( diff --git a/goofy-client/libs/test-utils/src/lib/helper.ts b/goofy-client/libs/test-utils/src/lib/helper.ts index 7c775584cf72b5bd3546ab540fdc24deb7661f68..0071199dcd46eaa0186b7976c45a57bc01964d88 100644 --- a/goofy-client/libs/test-utils/src/lib/helper.ts +++ b/goofy-client/libs/test-utils/src/lib/helper.ts @@ -25,4 +25,8 @@ export function dispatchEventFromFixture(fixture: ComponentFixture<any>, element export function getDebugElementFromFixtureByCss(fixture: ComponentFixture<any>, query: string): DebugElement { return fixture.debugElement.query(By.css(query)); -} \ No newline at end of file +} + +export function getElementFromDomRoot(fixture: ComponentFixture<any>, htmlElement: string): any { + return fixture.nativeElement.parentNode.querySelector(htmlElement); +} diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.html b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.html index 7cff27785933adb77a43e9155b796fd3efb9d9d8..bd0149c603b1ac42e4b6dbca6ccac8032e3208f2 100644 --- a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.html +++ b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.html @@ -1,14 +1,17 @@ -<goofy-client-icon-button-with-spinner icon="settings" toolTip="Einstellungen" +<goofy-client-icon-button-with-spinner icon="settings" toolTip="Einstellungen" data-test-id="user-settings-button" [matMenuTriggerFor]="settingsMenu"> </goofy-client-icon-button-with-spinner> -<mat-menu #settingsMenu="matMenu"> +<mat-menu #settingsMenu="matMenu" data-test-id="user-settings-menu"> <div class="menu-container" (click)="$event.stopPropagation()"> - <goofy-client-user-settings-email-benachrichtigung - [userSettings$]="userSettings$" - (valueChanged)="changeNotificationsSendFor($event)" - ></goofy-client-user-settings-email-benachrichtigung> - <goofy-client-user-settings-darkmode + <ng-container *ngIf="apiRoot$ | async as apiRoot"> + <goofy-client-user-settings-email-benachrichtigung data-test-id="user-settings-email-benachrichtigung" + *ngIf="apiRoot.resource | hasLink: apiRootLinkRel.CURRENT_USER" + [userSettings]="userSettings$ | async" + (valueChanged)="changeNotificationsSendFor($event)" + ></goofy-client-user-settings-email-benachrichtigung> + </ng-container> + <goofy-client-user-settings-darkmode data-test-id="user-settings-dark-mode" [darkMode$]="darkMode$" (darkModeEmitter)="changeColorMode($event)" ></goofy-client-user-settings-darkmode> diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.spec.ts b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.spec.ts index d11f9673e482b3b32a9c60b9f203382028210041..7f07852165f6ad8e4d01e56c877630e66bfba2c3 100644 --- a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.spec.ts +++ b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.spec.ts @@ -1,12 +1,18 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { MatButtonModule } from '@angular/material/button'; import { MatMenuModule } from '@angular/material/menu'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { ApiRootFacade, ApiRootLinkRel } from '@goofy-client/api-root-shared'; import { AppService } from '@goofy-client/app-shared'; -import { mock } from '@goofy-client/test-utils'; +import { createStateResource, HasLinkPipe } from '@goofy-client/tech-shared'; +import { getElementFromDomRoot, mock } from '@goofy-client/test-utils'; import { IconButtonWithSpinnerComponent } from '@goofy-client/ui'; import { UserSettingsService } from '@goofy-client/user-settings-shared'; +import { createApiRootResource } from 'libs/api-root-shared/test/api-root'; +import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; import { NotificationsSendFor } from 'libs/user-settings-shared/src/lib/user-settings.model'; import { MockComponent } from 'ng-mocks'; -import { BehaviorSubject } from 'rxjs'; +import { BehaviorSubject, of } from 'rxjs'; import { UserSettingsContainerComponent } from './user-settings-container.component'; import { UserSettingsDarkmodeComponent } from './user-settings-darkmode/user-settings-darkmode.component'; import { UserSettingsEmailBenachrichtigungComponent } from './user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component'; @@ -14,15 +20,27 @@ import { UserSettingsEmailBenachrichtigungComponent } from './user-settings-emai describe('UserSettingsContainerComponent', () => { let component: UserSettingsContainerComponent; let fixture: ComponentFixture<UserSettingsContainerComponent>; + let menuButtonElement; const darkModeSubj: BehaviorSubject<boolean> = new BehaviorSubject(false); const appService = { ...mock(AppService), getDarkMode: () => darkModeSubj }; const userSettingsService = { ...mock(UserSettingsService), setUserSettings: jest.fn() }; + const apiRootFacade = { ...mock(ApiRootFacade), getApiRoot: jest.fn() }; + + // const menu: string = getDataTestIdOf('user-settings-menu'); + const menuButton = getDataTestIdOf('user-settings-button'); + const emailBenachrichtigung: string = getDataTestIdOf('user-settings-email-benachrichtigung'); + const darkMode: string = getDataTestIdOf('user-settings-dark-mode'); beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [MatMenuModule], + imports: [ + NoopAnimationsModule, + MatButtonModule, + MatMenuModule + ], declarations: [ + HasLinkPipe, UserSettingsContainerComponent, MockComponent(UserSettingsDarkmodeComponent), MockComponent(UserSettingsEmailBenachrichtigungComponent), @@ -36,6 +54,10 @@ describe('UserSettingsContainerComponent', () => { { provide: UserSettingsService, useValue: userSettingsService + }, + { + provide: ApiRootFacade, + useValue: apiRootFacade } ], }); @@ -44,13 +66,27 @@ describe('UserSettingsContainerComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(UserSettingsContainerComponent); component = fixture.componentInstance; - fixture.detectChanges(); + fixture.autoDetectChanges(true); + menuButtonElement = fixture.nativeElement.querySelector(menuButton); }); it('should create', () => { expect(component).toBeTruthy(); }); + describe('settings menu', () => { + it('should not have the menu open', async () => { + const menu = getElementFromDomRoot(fixture, '.mat-menu-panel'); + expect(menu).toBeFalsy(); + }); + + it('open the menu when clicking on the account button', async () => { + menuButtonElement.click(); + const menu = getElementFromDomRoot(fixture, '.mat-menu-panel'); + expect(menu).toBeTruthy(); + }); + }) + describe('change color mode', () => { it('should call app service', () => { @@ -60,6 +96,32 @@ describe('UserSettingsContainerComponent', () => { }) }) + describe('Toggle for "notifications send for"', () => { + it('should call apiRootFacade to get apiRoot', () => { + component.ngOnInit(); + + expect(apiRootFacade.getApiRoot).toHaveBeenCalled(); + }) + + it('should show if link exists', () => { + component.apiRoot$ = of(createStateResource(createApiRootResource([ApiRootLinkRel.CURRENT_USER]))); + + menuButtonElement.click(); + const element = getElementFromDomRoot(fixture, emailBenachrichtigung); + + expect(element).toBeInTheDocument(); + }) + + it('should hide if link not exists', () => { + component.apiRoot$ = of(createStateResource(createApiRootResource())); + + menuButtonElement.click(); + const element = getElementFromDomRoot(fixture, emailBenachrichtigung); + + expect(element).not.toBeInTheDocument(); + }) + }) + describe('change notifications send for', () => { it('should call service with ALL', () => { @@ -74,4 +136,13 @@ describe('UserSettingsContainerComponent', () => { expect(userSettingsService.setUserSettings).toHaveBeenCalledWith({ notificationsSendFor: NotificationsSendFor.NONE }); }) }) + + describe('Toggle for "Dark mode"', () => { + it('should be visible', () => { + menuButtonElement.click(); + const element = getElementFromDomRoot(fixture, darkMode); + + expect(element).toBeInstanceOf(HTMLElement); + }) + }) }); diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.ts b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.ts index 3ebe11daa5b45cdd973c475cd500f065bc3581d2..0bae193a62aae487febc81907cb1a543ef572080 100644 --- a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.ts +++ b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.ts @@ -1,7 +1,8 @@ import { DOCUMENT } from '@angular/common'; import { Component, Inject, OnInit, Renderer2 } from '@angular/core'; +import { ApiRootFacade, ApiRootLinkRel, ApiRootResource } from '@goofy-client/api-root-shared'; import { AppService, localStorageDark } from '@goofy-client/app-shared'; -import { StateResource } from '@goofy-client/tech-shared'; +import { createEmptyStateResource, StateResource } from '@goofy-client/tech-shared'; import { UserSettingsService } from '@goofy-client/user-settings-shared'; import { NotificationsSendFor, UserSettings, UserSettingsResource } from 'libs/user-settings-shared/src/lib/user-settings.model'; import { Observable, of } from 'rxjs'; @@ -14,11 +15,15 @@ import { Observable, of } from 'rxjs'; export class UserSettingsContainerComponent implements OnInit { darkMode$: Observable<boolean> = of(true); userSettings$: Observable<StateResource<UserSettingsResource>>; + apiRoot$: Observable<StateResource<ApiRootResource>> = of(createEmptyStateResource<ApiRootResource>()); + + readonly apiRootLinkRel = ApiRootLinkRel; constructor( private renderer: Renderer2, private appService: AppService, private userSettingsService: UserSettingsService, + private apiRootFacade: ApiRootFacade, @Inject(DOCUMENT) private document: Document ) { this.darkMode$ = this.appService.getDarkMode(); @@ -28,6 +33,7 @@ export class UserSettingsContainerComponent implements OnInit { ngOnInit(): void { this.userSettings$ = this.userSettingsService.getUserSettings(); + this.apiRoot$ = this.apiRootFacade.getApiRoot(); } private subscribeToDarkMode(): void { diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.html b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.html index 90823c5225e8680fc0f3c4e8f2d59ada0db9366e..4ee42fd2ca5a16c25d8a7404a9b8ff2115096474 100644 --- a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.html +++ b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.html @@ -1,8 +1,8 @@ -<ng-container *ngIf="(userSettings$ | async)?.resource as userSettings"> +<ng-container *ngIf="userSettings.resource"> <mat-slide-toggle data-test-id="toggle-notifications-send-for" color="primary" matTooltip="Benachrichtigung per E-Mail bei Eingang eines Antrags" - [checked]="getToggleStatus(userSettings)" + [checked]="getToggleStatus(userSettings.resource)" (change)="valueChanged.emit($event.checked)">Benachrichtigung per E-Mail </mat-slide-toggle> </ng-container> \ No newline at end of file diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.spec.ts b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.spec.ts index 84969ed2659f95fb7dd76e3fd5eb56be1719b2f2..4455f44a77af3323d0de67d23f70f175c5e99c1a 100644 --- a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.spec.ts +++ b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.spec.ts @@ -8,7 +8,6 @@ import { dispatchEventFromFixture, mock } from '@goofy-client/test-utils'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; import { NotificationsSendFor } from 'libs/user-settings-shared/src/lib/user-settings.model'; import { createUserSettings, createUserSettingsResource } from 'libs/user-settings-shared/test/user-settings'; -import { of } from 'rxjs'; import { EventEmitter } from 'stream'; import { UserSettingsEmailBenachrichtigungComponent } from './user-settings-email-benachrichtigung.component'; @@ -29,7 +28,7 @@ describe('UserSettingsEmailBenachrichtigungComponent', () => { UserSettingsEmailBenachrichtigungComponent ); component = fixture.componentInstance; - component.userSettings$ = of(createStateResource(createUserSettingsResource())); + component.userSettings = createStateResource(createUserSettingsResource()); component.valueChanged = { ...<any>mock(EventEmitter), emit: jest.fn() }; fixture.detectChanges(); }); diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.ts b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.ts index adb1df1f939759d85464ac9503323a94759f55c2..185a0d82cb6fadf2faf58cb9032a55ca53c911b1 100644 --- a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.ts +++ b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.ts @@ -1,7 +1,6 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; -import { StateResource } from '@goofy-client/tech-shared'; +import { createEmptyStateResource, StateResource } from '@goofy-client/tech-shared'; import { NotificationsSendFor, UserSettings, UserSettingsResource } from '@goofy-client/user-settings-shared'; -import { Observable } from 'rxjs'; @Component({ selector: 'goofy-client-user-settings-email-benachrichtigung', @@ -9,7 +8,7 @@ import { Observable } from 'rxjs'; styleUrls: ['./user-settings-email-benachrichtigung.component.scss'], }) export class UserSettingsEmailBenachrichtigungComponent { - @Input() userSettings$: Observable<StateResource<UserSettingsResource>>; + @Input() userSettings: StateResource<UserSettingsResource> = createEmptyStateResource<UserSettingsResource>(); @Output() valueChanged: EventEmitter<boolean> = new EventEmitter(); public getToggleStatus(userSettings: UserSettings): boolean { diff --git a/goofy-client/libs/user-settings/src/test-setup.ts b/goofy-client/libs/user-settings/src/test-setup.ts index 08ef82b5d5efa87cb27257314075f6a16eb7a63e..82178098b34faeb3a94a8268bd072d4db95371a3 100644 --- a/goofy-client/libs/user-settings/src/test-setup.ts +++ b/goofy-client/libs/user-settings/src/test-setup.ts @@ -1,9 +1,10 @@ +import '@testing-library/jest-dom'; import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { BrowserDynamicTestingModule, - platformBrowserDynamicTesting, + platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment();