From f24234c4adbc689bfdf00924f591f3223581f40f Mon Sep 17 00:00:00 2001
From: OZGCloud <ozgcloud@mgm-tp.com>
Date: Wed, 4 Dec 2024 17:55:00 +0100
Subject: [PATCH] OZG-7000 feature toggle in navigation and pages

---
 .../apps/admin/src/app/app.component.html     | 30 ++++++----
 .../apps/admin/src/app/app.component.spec.ts  | 58 ++++++++++++++++++-
 .../apps/admin/src/app/app.component.ts       |  2 +
 ...anisationseinheit-form-page.component.html |  6 +-
 ...sationseinheit-form-page.component.spec.ts | 44 ++++++++++++++
 ...rganisationseinheit-form-page.component.ts | 17 +++++-
 .../organisationseinheit-page.component.html  |  6 +-
 ...rganisationseinheit-page.component.spec.ts | 34 +++++++++++
 .../organisationseinheit-page.component.ts    | 16 ++++-
 .../postfach-page.component.html              |  4 +-
 .../postfach-page.component.spec.ts           | 26 ++++++++-
 .../postfach-page/postfach-page.component.ts  |  5 +-
 .../user-add-page.component.html              |  4 +-
 .../user-add-page.component.spec.ts           | 25 ++++++++
 .../user-add-page/user-add-page.component.ts  |  5 +-
 .../user-roles-page.component.html            |  4 +-
 .../user-roles-page.component.spec.ts         | 25 ++++++++
 .../user-roles-page.component.ts              |  5 +-
 .../src/lib/environment.model.ts              |  4 ++
 .../environment-shared/test/environment.ts    |  4 ++
 20 files changed, 300 insertions(+), 24 deletions(-)

diff --git a/alfa-client/apps/admin/src/app/app.component.html b/alfa-client/apps/admin/src/app/app.component.html
index 9e3f549e41..b8a2a57f09 100644
--- a/alfa-client/apps/admin/src/app/app.component.html
+++ b/alfa-client/apps/admin/src/app/app.component.html
@@ -16,16 +16,26 @@
   <div class="flex h-screen w-full justify-center overflow-y-auto">
     <ods-navbar data-test-id="navigation">
       <ng-container *ngIf="apiRoot | hasLink: ApiRootLinkRel.CONFIGURATION">
-        <ods-nav-item caption="Benutzer & Rollen" path="/benutzer_und_rollen">
-          <ods-users-icon class="stroke-text" icon />
-        </ods-nav-item>
-        <hr />
-        <ods-nav-item caption="Postfach" path="/postfach">
-          <ods-mailbox-icon icon />
-        </ods-nav-item>
-        <ods-nav-item caption="Organisationseinheiten" path="/organisationseinheiten">
-          <ods-orga-unit-icon icon />
-        </ods-nav-item>
+        <ng-container *ngIf="environment.features.benutzerRollen">
+          <ods-nav-item data-test-id="users-roles-navigation" caption="Benutzer & Rollen" path="/benutzer_und_rollen">
+            <ods-users-icon class="stroke-text" icon />
+          </ods-nav-item>
+          <hr />
+        </ng-container>
+        <ng-container *ngIf="environment.features.postfach">
+          <ods-nav-item data-test-id="postfach-navigation" caption="Postfach" path="/postfach">
+            <ods-mailbox-icon icon />
+          </ods-nav-item>
+        </ng-container>
+        <ng-container *ngIf="apiRoot | hasLink: ApiRootLinkRel.ORGANISATIONS_EINHEIT">
+          <ods-nav-item
+            data-test-id="organisations-einheiten-navigation"
+            caption="Organisationseinheiten"
+            path="/organisationseinheiten"
+          >
+            <ods-orga-unit-icon icon />
+          </ods-nav-item>
+        </ng-container>
       </ng-container>
     </ods-navbar>
     <main class="flex-1 overflow-y-auto bg-white px-6 py-4">
diff --git a/alfa-client/apps/admin/src/app/app.component.spec.ts b/alfa-client/apps/admin/src/app/app.component.spec.ts
index 547e092331..212128e52b 100644
--- a/alfa-client/apps/admin/src/app/app.component.spec.ts
+++ b/alfa-client/apps/admin/src/app/app.component.spec.ts
@@ -1,5 +1,6 @@
 import { ApiRootLinkRel, ApiRootResource, ApiRootService } from '@alfa-client/api-root-shared';
 import { BuildInfoComponent } from '@alfa-client/common';
+import { Environment } from '@alfa-client/environment-shared';
 import { HasLinkPipe, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared';
 import {
   Mock,
@@ -24,6 +25,7 @@ import { createApiRootResource } from 'libs/api-root-shared/test/api-root';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { MockComponent, MockDirective } from 'ng-mocks';
 import { of } from 'rxjs';
+import { createEnvironment } from '../../../../libs/environment-shared/test/environment';
 import { UserProfileButtonContainerComponent } from '../common/user-profile-button-container/user-profile.button-container.component';
 import { UnavailablePageComponent } from '../pages/unavailable/unavailable-page/unavailable-page.component';
 import { AppComponent } from './app.component';
@@ -36,9 +38,14 @@ describe('AppComponent', () => {
   const buildInfoSelector: string = getDataTestIdOf('build-info');
   const userProfileButtonSelector: string = getDataTestIdOf('user-profile-button');
   const navigationSelector: string = getDataTestIdOf('navigation');
+  const usersRolesNavigationSelector: string = getDataTestIdOf('users-roles-navigation');
+  const postfachNavigationSelector: string = getDataTestIdOf('postfach-navigation');
+  const organisationsEinheitenNavigationSelector: string = getDataTestIdOf('organisations-einheiten-navigation');
   const logoLink: string = getDataTestIdOf('logo-link');
   const routerOutletSelector: string = getDataTestIdOf('router-outlet');
 
+  let environment: Environment;
+
   const authenticationService: Mock<AuthenticationService> = {
     ...mock(AuthenticationService),
     login: jest.fn().mockResolvedValue(Promise.resolve()),
@@ -97,6 +104,9 @@ describe('AppComponent', () => {
   });
 
   beforeEach(() => {
+    environment = createEnvironment();
+    window['__env__'] = environment;
+
     fixture = TestBed.createComponent(AppComponent);
     component = fixture.componentInstance;
   });
@@ -185,8 +195,11 @@ describe('AppComponent', () => {
     });
 
     describe('navigation', () => {
-      it('should show links if configuration link exists', () => {
+      beforeEach(() => {
         component.apiRootStateResource$ = of(createStateResource(createApiRootResource([ApiRootLinkRel.CONFIGURATION])));
+      });
+
+      it('should show links if configuration link exists', () => {
         fixture.detectChanges();
 
         const navbarElement: HTMLElement = getElementFromFixture(fixture, navigationSelector);
@@ -202,6 +215,49 @@ describe('AppComponent', () => {
 
         expect(navbarElement.children.length).toBe(0);
       });
+
+      it('should show postfach link if postfach feature toggle is true', () => {
+        component.environment.features.postfach = true;
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, postfachNavigationSelector);
+      });
+
+      it('should not show postfach link if postfach feature toggle is false', () => {
+        component.environment.features.postfach = false;
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, postfachNavigationSelector);
+      });
+
+      it('should show benutzer & rollen if benutzerRollen feature toggle is true', () => {
+        component.environment.features.benutzerRollen = true;
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, usersRolesNavigationSelector);
+      });
+
+      it('should not show benutzer & rollen if benutzerRollen feature toggle is false', () => {
+        component.environment.features.benutzerRollen = false;
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, usersRolesNavigationSelector);
+      });
+
+      it('should show organisationsEinheiten if link in apiRoot exists', () => {
+        component.apiRootStateResource$ = of(
+          createStateResource(createApiRootResource([ApiRootLinkRel.ORGANISATIONS_EINHEIT, ApiRootLinkRel.CONFIGURATION])),
+        );
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, organisationsEinheitenNavigationSelector);
+      });
+
+      it('should not show organisationsEinheiten if link in apiRoot does not exist', () => {
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, organisationsEinheitenNavigationSelector);
+      });
     });
 
     describe('build version', () => {
diff --git a/alfa-client/apps/admin/src/app/app.component.ts b/alfa-client/apps/admin/src/app/app.component.ts
index e1d4c6d2a4..369adaaa96 100644
--- a/alfa-client/apps/admin/src/app/app.component.ts
+++ b/alfa-client/apps/admin/src/app/app.component.ts
@@ -1,4 +1,5 @@
 import { ApiRootLinkRel, ApiRootResource, ApiRootService } from '@alfa-client/api-root-shared';
+import { Environment, getEnvironmentFactory } from '@alfa-client/environment-shared';
 import { StateResource } from '@alfa-client/tech-shared';
 import { Component, OnInit } from '@angular/core';
 import { ActivatedRoute, Params, Router } from '@angular/router';
@@ -14,6 +15,7 @@ export class AppComponent implements OnInit {
   readonly title = 'admin';
 
   public apiRootStateResource$: Observable<StateResource<ApiRootResource>>;
+  public environment: Environment = getEnvironmentFactory();
 
   constructor(
     public authenticationService: AuthenticationService,
diff --git a/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-form-page/organisationseinheit-form-page.component.html b/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-form-page/organisationseinheit-form-page.component.html
index 2449a303b1..71a2c7edd3 100644
--- a/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-form-page/organisationseinheit-form-page.component.html
+++ b/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-form-page/organisationseinheit-form-page.component.html
@@ -1 +1,5 @@
-<admin-organisationseinheit-form-container/>
\ No newline at end of file
+<ng-container *ngIf="(apiRootStateResource$ | async)?.resource as apiRoot">
+  @if(apiRoot | hasLink: ApiRootLinkRel.ORGANISATIONS_EINHEIT){
+    <admin-organisationseinheit-form-container data-test-id="organisations-einheit-form"/>
+  }
+</ng-container>
diff --git a/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-form-page/organisationseinheit-form-page.component.spec.ts b/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-form-page/organisationseinheit-form-page.component.spec.ts
index 4ad49ca459..eb70d91232 100644
--- a/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-form-page/organisationseinheit-form-page.component.spec.ts
+++ b/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-form-page/organisationseinheit-form-page.component.spec.ts
@@ -1,15 +1,31 @@
 import { OrganisationsEinheitFormContainerComponent } from '@admin-client/admin-settings';
+import { ApiRootLinkRel, ApiRootService } from '@alfa-client/api-root-shared';
+import { createStateResource, TechSharedModule } from '@alfa-client/tech-shared';
+import { existsAsHtmlElement, mock, Mock, notExistsAsHtmlElement } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { createApiRootResource } from 'libs/api-root-shared/test/api-root';
+import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { MockComponent } from 'ng-mocks';
+import { of } from 'rxjs';
 import { OrganisationsEinheitFormPageComponent } from './organisationseinheit-form-page.component';
 
 describe('OrganisationsEinheitFormPageComponent', () => {
   let component: OrganisationsEinheitFormPageComponent;
   let fixture: ComponentFixture<OrganisationsEinheitFormPageComponent>;
 
+  const organisationsEinheitFormSelector: string = getDataTestIdOf('organisations-einheit-form');
+
+  const apiRootStateResource$ = of(createStateResource(createApiRootResource()));
+  const apiRootService: Mock<ApiRootService> = {
+    ...mock(ApiRootService),
+    getApiRoot: jest.fn().mockReturnValue(apiRootStateResource$),
+  };
+
   beforeEach(async () => {
     await TestBed.configureTestingModule({
+      imports: [TechSharedModule],
       declarations: [OrganisationsEinheitFormPageComponent, MockComponent(OrganisationsEinheitFormContainerComponent)],
+      providers: [{ provide: ApiRootService, useValue: apiRootService }],
     }).compileComponents();
   });
 
@@ -23,4 +39,32 @@ describe('OrganisationsEinheitFormPageComponent', () => {
   it('should create', () => {
     expect(component).toBeTruthy();
   });
+
+  describe('component', () => {
+    describe('ngOnInit', () => {
+      it('should get apiRoot', () => {
+        component.ngOnInit();
+
+        expect(component.apiRootStateResource$).toBe(apiRootStateResource$);
+      });
+    });
+  });
+
+  describe('template', () => {
+    describe('admin-organisationseinheit-form-container', () => {
+      it('should be rendered if apiRootState has link', () => {
+        component.apiRootStateResource$ = of(createStateResource(createApiRootResource([ApiRootLinkRel.ORGANISATIONS_EINHEIT])));
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, organisationsEinheitFormSelector);
+      });
+
+      it('should not be rendered if apiRootState has no link', () => {
+        component.apiRootStateResource$ = of(createStateResource(createApiRootResource()));
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, organisationsEinheitFormSelector);
+      });
+    });
+  });
 });
diff --git a/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-form-page/organisationseinheit-form-page.component.ts b/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-form-page/organisationseinheit-form-page.component.ts
index b7c9e0ea72..6a14ce6da4 100644
--- a/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-form-page/organisationseinheit-form-page.component.ts
+++ b/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-form-page/organisationseinheit-form-page.component.ts
@@ -1,7 +1,20 @@
-import { Component } from '@angular/core';
+import { ApiRootLinkRel, ApiRootResource, ApiRootService } from '@alfa-client/api-root-shared';
+import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared';
+import { Component, inject, OnInit } from '@angular/core';
+import { Observable, of } from 'rxjs';
 
 @Component({
   selector: 'organisationseinheit-form-page',
   templateUrl: './organisationseinheit-form-page.component.html',
 })
-export class OrganisationsEinheitFormPageComponent {}
+export class OrganisationsEinheitFormPageComponent implements OnInit {
+  private apiRootService = inject(ApiRootService);
+
+  public apiRootStateResource$: Observable<StateResource<ApiRootResource>> = of(createEmptyStateResource<ApiRootResource>());
+
+  ngOnInit(): void {
+    this.apiRootStateResource$ = this.apiRootService.getApiRoot();
+  }
+
+  protected readonly ApiRootLinkRel = ApiRootLinkRel;
+}
diff --git a/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-page/organisationseinheit-page.component.html b/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-page/organisationseinheit-page.component.html
index 7929301587..d57d0eb794 100644
--- a/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-page/organisationseinheit-page.component.html
+++ b/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-page/organisationseinheit-page.component.html
@@ -1 +1,5 @@
-<admin-organisationseinheit-container/>
+<ng-container *ngIf="(apiRootStateResource$ | async)?.resource as apiRoot">
+  @if(apiRoot | hasLink: ApiRootLinkRel.ORGANISATIONS_EINHEIT){
+    <admin-organisationseinheit-container data-test-id="organisations-einheit-container"/>
+  }
+</ng-container>
\ No newline at end of file
diff --git a/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-page/organisationseinheit-page.component.spec.ts b/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-page/organisationseinheit-page.component.spec.ts
index 59ddda81ab..17a5736eae 100644
--- a/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-page/organisationseinheit-page.component.spec.ts
+++ b/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-page/organisationseinheit-page.component.spec.ts
@@ -1,15 +1,31 @@
 import { OrganisationsEinheitContainerComponent } from '@admin-client/admin-settings';
+import { ApiRootLinkRel, ApiRootService } from '@alfa-client/api-root-shared';
+import { createStateResource, TechSharedModule } from '@alfa-client/tech-shared';
+import { existsAsHtmlElement, mock, Mock, notExistsAsHtmlElement } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MockComponent } from 'ng-mocks';
+import { of } from 'rxjs';
+import { createApiRootResource } from '../../../../../../libs/api-root-shared/test/api-root';
+import { getDataTestIdOf } from '../../../../../../libs/tech-shared/test/data-test';
 import { OrganisationsEinheitPageComponent } from './organisationseinheit-page.component';
 
 describe('OrganisationsEinheitPageComponent', () => {
   let component: OrganisationsEinheitPageComponent;
   let fixture: ComponentFixture<OrganisationsEinheitPageComponent>;
 
+  const organisationsEinheitContainerSelector: string = getDataTestIdOf('organisations-einheit-container');
+
+  const apiRootStateResource$ = of(createStateResource(createApiRootResource()));
+  const apiRootService: Mock<ApiRootService> = {
+    ...mock(ApiRootService),
+    getApiRoot: jest.fn().mockReturnValue(apiRootStateResource$),
+  };
+
   beforeEach(async () => {
     await TestBed.configureTestingModule({
+      imports: [TechSharedModule],
       declarations: [OrganisationsEinheitPageComponent, MockComponent(OrganisationsEinheitContainerComponent)],
+      providers: [{ provide: ApiRootService, useValue: apiRootService }],
     }).compileComponents();
   });
 
@@ -23,4 +39,22 @@ describe('OrganisationsEinheitPageComponent', () => {
   it('should create', () => {
     expect(component).toBeTruthy();
   });
+
+  describe('template', () => {
+    describe('admin-organisationseinheit-container', () => {
+      it('should be rendered if apiRootState has link', () => {
+        component.apiRootStateResource$ = of(createStateResource(createApiRootResource([ApiRootLinkRel.ORGANISATIONS_EINHEIT])));
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, organisationsEinheitContainerSelector);
+      });
+
+      it('should not be rendered if apiRootState has no link', () => {
+        component.apiRootStateResource$ = of(createStateResource(createApiRootResource()));
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, organisationsEinheitContainerSelector);
+      });
+    });
+  });
 });
diff --git a/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-page/organisationseinheit-page.component.ts b/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-page/organisationseinheit-page.component.ts
index 4d653b6ed7..08fdbd714d 100644
--- a/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-page/organisationseinheit-page.component.ts
+++ b/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-page/organisationseinheit-page.component.ts
@@ -1,7 +1,19 @@
-import { Component } from '@angular/core';
+import { ApiRootLinkRel, ApiRootResource, ApiRootService } from '@alfa-client/api-root-shared';
+import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared';
+import { Component, inject } from '@angular/core';
+import { Observable, of } from 'rxjs';
 
 @Component({
   selector: 'organisationseinheit-page',
   templateUrl: './organisationseinheit-page.component.html',
 })
-export class OrganisationsEinheitPageComponent {}
+export class OrganisationsEinheitPageComponent {
+  private apiRootService = inject(ApiRootService);
+
+  public apiRootStateResource$: Observable<StateResource<ApiRootResource>> = of(createEmptyStateResource<ApiRootResource>());
+
+  ngOnInit(): void {
+    this.apiRootStateResource$ = this.apiRootService.getApiRoot();
+  }
+  protected readonly ApiRootLinkRel = ApiRootLinkRel;
+}
diff --git a/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.html b/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.html
index 35312d3a6f..6d30a459ec 100644
--- a/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.html
+++ b/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.html
@@ -1 +1,3 @@
-<admin-postfach-container></admin-postfach-container>
+@if(environment.features.postfach){
+  <admin-postfach-container data-test-id="postfach-container"/>
+}
\ No newline at end of file
diff --git a/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.spec.ts b/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.spec.ts
index 5ebec9f21a..49c04dc617 100644
--- a/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.spec.ts
+++ b/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.spec.ts
@@ -1,12 +1,18 @@
 import { PostfachContainerComponent } from '@admin-client/admin-settings';
+import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MockComponent } from 'ng-mocks';
+import { createEnvironment } from '../../../../../../libs/environment-shared/test/environment';
+import { getDataTestIdOf } from '../../../../../../libs/tech-shared/test/data-test';
 import { PostfachPageComponent } from './postfach-page.component';
 
 describe('PostfachPageComponent', () => {
   let component: PostfachPageComponent;
   let fixture: ComponentFixture<PostfachPageComponent>;
 
+  const postfachContainerSelector: string = getDataTestIdOf('postfach-container');
+  const environment = createEnvironment();
+
   beforeEach(async () => {
     await TestBed.configureTestingModule({
       declarations: [PostfachPageComponent, MockComponent(PostfachContainerComponent)],
@@ -16,11 +22,29 @@ describe('PostfachPageComponent', () => {
   beforeEach(() => {
     fixture = TestBed.createComponent(PostfachPageComponent);
     component = fixture.componentInstance;
-
+    component.environment = environment;
     fixture.detectChanges();
   });
 
   it('should create', () => {
     expect(component).toBeTruthy();
   });
+
+  describe('template', () => {
+    describe('admin-postfach-container', () => {
+      it('should be rendered if feature toggle postfach is true', () => {
+        environment.features.postfach = true;
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, postfachContainerSelector);
+      });
+
+      it('should not be rendered if feature toggle postfach is false', () => {
+        environment.features.postfach = false;
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, postfachContainerSelector);
+      });
+    });
+  });
 });
diff --git a/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.ts b/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.ts
index 1d9a54cedd..e517dd361f 100644
--- a/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.ts
+++ b/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.ts
@@ -1,7 +1,10 @@
+import { Environment, getEnvironmentFactory } from '@alfa-client/environment-shared';
 import { Component } from '@angular/core';
 
 @Component({
   selector: 'postfach-page',
   templateUrl: './postfach-page.component.html',
 })
-export class PostfachPageComponent {}
+export class PostfachPageComponent {
+  public environment: Environment = getEnvironmentFactory();
+}
diff --git a/alfa-client/apps/admin/src/pages/users-roles/user-add-page/user-add-page.component.html b/alfa-client/apps/admin/src/pages/users-roles/user-add-page/user-add-page.component.html
index dad58a8662..b6866e0ee5 100644
--- a/alfa-client/apps/admin/src/pages/users-roles/user-add-page/user-add-page.component.html
+++ b/alfa-client/apps/admin/src/pages/users-roles/user-add-page/user-add-page.component.html
@@ -1 +1,3 @@
-<admin-user-add-form />
+@if(environment.features.benutzerRollen){
+  <admin-user-add-form data-test-id="user-add-form"/>
+}
\ No newline at end of file
diff --git a/alfa-client/apps/admin/src/pages/users-roles/user-add-page/user-add-page.component.spec.ts b/alfa-client/apps/admin/src/pages/users-roles/user-add-page/user-add-page.component.spec.ts
index eecaa8e5c0..4a3016f2eb 100644
--- a/alfa-client/apps/admin/src/pages/users-roles/user-add-page/user-add-page.component.spec.ts
+++ b/alfa-client/apps/admin/src/pages/users-roles/user-add-page/user-add-page.component.spec.ts
@@ -1,5 +1,8 @@
 import { UserAddFormComponent } from '@admin-client/admin-settings';
+import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { createEnvironment } from 'libs/environment-shared/test/environment';
+import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { MockComponent } from 'ng-mocks';
 import { UserAddPageComponent } from './user-add-page.component';
 
@@ -7,6 +10,9 @@ describe('UserAddPageComponent', () => {
   let component: UserAddPageComponent;
   let fixture: ComponentFixture<UserAddPageComponent>;
 
+  const userAddFormSelector: string = getDataTestIdOf('user-add-form');
+  const environment = createEnvironment();
+
   beforeEach(async () => {
     await TestBed.configureTestingModule({
       declarations: [UserAddPageComponent, MockComponent(UserAddFormComponent)],
@@ -14,10 +20,29 @@ describe('UserAddPageComponent', () => {
 
     fixture = TestBed.createComponent(UserAddPageComponent);
     component = fixture.componentInstance;
+    component.environment = environment;
     fixture.detectChanges();
   });
 
   it('should create', () => {
     expect(component).toBeTruthy();
   });
+
+  describe('template', () => {
+    describe('admin-user-add-form', () => {
+      it('should be rendered if feature toggle for benutzerRollen is true', () => {
+        environment.features.benutzerRollen = true;
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, userAddFormSelector);
+      });
+
+      it('should not be rendered if feature toggle for benutzerRollen is false', () => {
+        environment.features.benutzerRollen = false;
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, userAddFormSelector);
+      });
+    });
+  });
 });
diff --git a/alfa-client/apps/admin/src/pages/users-roles/user-add-page/user-add-page.component.ts b/alfa-client/apps/admin/src/pages/users-roles/user-add-page/user-add-page.component.ts
index f3bcc1eaf5..e52105d82b 100644
--- a/alfa-client/apps/admin/src/pages/users-roles/user-add-page/user-add-page.component.ts
+++ b/alfa-client/apps/admin/src/pages/users-roles/user-add-page/user-add-page.component.ts
@@ -1,7 +1,10 @@
+import { Environment, getEnvironmentFactory } from '@alfa-client/environment-shared';
 import { Component } from '@angular/core';
 
 @Component({
   selector: 'user-add-page',
   templateUrl: './user-add-page.component.html',
 })
-export class UserAddPageComponent {}
+export class UserAddPageComponent {
+  public environment: Environment = getEnvironmentFactory();
+}
diff --git a/alfa-client/apps/admin/src/pages/users-roles/user-roles-page/user-roles-page.component.html b/alfa-client/apps/admin/src/pages/users-roles/user-roles-page/user-roles-page.component.html
index 3000e0ffba..dc2545d652 100644
--- a/alfa-client/apps/admin/src/pages/users-roles/user-roles-page/user-roles-page.component.html
+++ b/alfa-client/apps/admin/src/pages/users-roles/user-roles-page/user-roles-page.component.html
@@ -1 +1,3 @@
-<admin-users-roles />
\ No newline at end of file
+@if(environment.features.benutzerRollen){
+  <admin-users-roles data-test-id="users-roles"/>
+}
diff --git a/alfa-client/apps/admin/src/pages/users-roles/user-roles-page/user-roles-page.component.spec.ts b/alfa-client/apps/admin/src/pages/users-roles/user-roles-page/user-roles-page.component.spec.ts
index 1285eda740..0819e2bec0 100644
--- a/alfa-client/apps/admin/src/pages/users-roles/user-roles-page/user-roles-page.component.spec.ts
+++ b/alfa-client/apps/admin/src/pages/users-roles/user-roles-page/user-roles-page.component.spec.ts
@@ -1,5 +1,8 @@
 import { UsersRolesComponent } from '@admin-client/admin-settings';
+import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { createEnvironment } from 'libs/environment-shared/test/environment';
+import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { MockComponent } from 'ng-mocks';
 import { UserRolesPageComponent } from './user-roles-page.component';
 
@@ -7,6 +10,9 @@ describe('UserRolesPageComponent', () => {
   let component: UserRolesPageComponent;
   let fixture: ComponentFixture<UserRolesPageComponent>;
 
+  const usersRolesSelector: string = getDataTestIdOf('users-roles');
+  const environment = createEnvironment();
+
   beforeEach(async () => {
     await TestBed.configureTestingModule({
       declarations: [UserRolesPageComponent],
@@ -15,10 +21,29 @@ describe('UserRolesPageComponent', () => {
 
     fixture = TestBed.createComponent(UserRolesPageComponent);
     component = fixture.componentInstance;
+    component.environment = environment;
     fixture.detectChanges();
   });
 
   it('should create', () => {
     expect(component).toBeTruthy();
   });
+
+  describe('template', () => {
+    describe('admin-users-roles', () => {
+      it('should be rendered if feature toggle benutzerRollen is true', () => {
+        environment.features.benutzerRollen = true;
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, usersRolesSelector);
+      });
+
+      it('should not be rendered component if feature toggle benutzerRollen is false', () => {
+        environment.features.benutzerRollen = false;
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, usersRolesSelector);
+      });
+    });
+  });
 });
diff --git a/alfa-client/apps/admin/src/pages/users-roles/user-roles-page/user-roles-page.component.ts b/alfa-client/apps/admin/src/pages/users-roles/user-roles-page/user-roles-page.component.ts
index 6b3576a76e..eacc7b424e 100644
--- a/alfa-client/apps/admin/src/pages/users-roles/user-roles-page/user-roles-page.component.ts
+++ b/alfa-client/apps/admin/src/pages/users-roles/user-roles-page/user-roles-page.component.ts
@@ -1,7 +1,10 @@
+import { Environment, getEnvironmentFactory } from '@alfa-client/environment-shared';
 import { Component } from '@angular/core';
 
 @Component({
   selector: 'app-user-roles-page',
   templateUrl: './user-roles-page.component.html',
 })
-export class UserRolesPageComponent {}
+export class UserRolesPageComponent {
+  public environment: Environment = getEnvironmentFactory();
+}
diff --git a/alfa-client/libs/environment-shared/src/lib/environment.model.ts b/alfa-client/libs/environment-shared/src/lib/environment.model.ts
index a20dc12279..0944f55da0 100644
--- a/alfa-client/libs/environment-shared/src/lib/environment.model.ts
+++ b/alfa-client/libs/environment-shared/src/lib/environment.model.ts
@@ -30,4 +30,8 @@ export interface Environment {
   realm: string;
   clientId: string;
   processorNames: string[];
+  features: {
+    postfach: boolean;
+    benutzerRollen: boolean;
+  };
 }
diff --git a/alfa-client/libs/environment-shared/test/environment.ts b/alfa-client/libs/environment-shared/test/environment.ts
index de7f1c09bf..4fe7192ae4 100644
--- a/alfa-client/libs/environment-shared/test/environment.ts
+++ b/alfa-client/libs/environment-shared/test/environment.ts
@@ -32,6 +32,10 @@ const environment: Environment = {
   realm: faker.word.sample(),
   clientId: faker.string.uuid(),
   processorNames: [faker.person.fullName()],
+  features: {
+    postfach: true,
+    benutzerRollen: true,
+  },
 };
 
 export function createEnvironment(): Environment {
-- 
GitLab