Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 51 additions & 39 deletions src/app/modules/shared/components/sidebar/sidebar.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,62 @@
import {AzureAdB2CService} from 'src/app/modules/login/services/azure.ad.b2c.service';
import {waitForAsync, ComponentFixture, TestBed} from '@angular/core/testing';

import {SidebarComponent} from './sidebar.component';
import {RouterTestingModule} from '@angular/router/testing';
import {Router, Routes} from '@angular/router';
import {TimeClockComponent} from '../../../time-clock/pages/time-clock.component';
import {provideMockStore} from '@ngrx/store/testing';
import {of} from 'rxjs';
import {FeatureManagerService} from '../../feature-toggles/feature-toggle-manager.service';
import { AzureAdB2CService } from 'src/app/modules/login/services/azure.ad.b2c.service';
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { SidebarComponent } from './sidebar.component';
import { RouterTestingModule } from '@angular/router/testing';
import { Router, Routes } from '@angular/router';
import { TimeClockComponent } from '../../../time-clock/pages/time-clock.component';
import { of } from 'rxjs';
import { FeatureManagerService } from '../../feature-toggles/feature-toggle-manager.service';
import { FeatureSwitchGroupService } from '../../feature-toggles/switch-group/feature-switch-group.service';
import { UserInfoService } from 'src/app/modules/user/services/user-info.service';

describe('SidebarComponent', () => {
let component: SidebarComponent;
let fixture: ComponentFixture<SidebarComponent>;
let azureAdB2CServiceStubInjected;
let featureManagerServiceStubInjected: FeatureManagerService;
let featureSwitchGroupService: FeatureSwitchGroupService;
let userInfoService: UserInfoService;
let router;
const routes: Routes = [
{path: 'time-clock', component: TimeClockComponent}
];
const routes: Routes = [{ path: 'time-clock', component: TimeClockComponent }];

const azureAdB2CServiceStub = {
isLogin() {
return true;
},
isAdmin() {
return true;
}
},
};

const userInfoServiceStub = {
isAdmin: () => of(true),
};

const featureSwitchGroupServiceStub = {
isActivated: () => of(true),
};

beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [SidebarComponent],
providers: [
{providers: AzureAdB2CService, useValue: azureAdB2CServiceStub},
provideMockStore({initialState: {}})
],
imports: [RouterTestingModule.withRoutes(routes)]
beforeEach(
waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [SidebarComponent],
providers: [
{ provide: AzureAdB2CService, useValue: azureAdB2CServiceStub },
{ provide: FeatureSwitchGroupService, useValue: featureSwitchGroupServiceStub },
{ provide: UserInfoService, useValue: userInfoServiceStub },
],
imports: [RouterTestingModule.withRoutes(routes)],
}).compileComponents();
router = TestBed.inject(Router);
})
.compileComponents();
router = TestBed.inject(Router);
}));
);

beforeEach(() => {
fixture = TestBed.createComponent(SidebarComponent);
azureAdB2CServiceStubInjected = TestBed.inject(AzureAdB2CService);
featureManagerServiceStubInjected = TestBed.inject(FeatureManagerService);
featureSwitchGroupService = TestBed.inject(FeatureSwitchGroupService);
userInfoService = TestBed.inject(UserInfoService);
component = fixture.componentInstance;
fixture.detectChanges();
});
Expand All @@ -54,32 +66,33 @@ describe('SidebarComponent', () => {
expect(component).toBeTruthy();
});

it('admin users have five menu items', () => {
spyOn(azureAdB2CServiceStubInjected, 'isAdmin').and.returnValue(true);
it('admin users have six menu items', () => {
spyOn(featureSwitchGroupService, 'isActivated').and.returnValue(of(true));

component.getSidebarItems();
const menuItems = component.itemsSidebar;

expect(menuItems.length).toBe(6);
component.getSidebarItems().subscribe(() => {
const menuItems = component.itemsSidebar;
expect(menuItems.length).toBe(6);
});
});

it('non admin users have two menu items', () => {
spyOn(azureAdB2CServiceStubInjected, 'isAdmin').and.returnValue(false);
spyOn(featureSwitchGroupService, 'isActivated').and.returnValue(of(true));
spyOn(userInfoServiceStub, 'isAdmin').and.returnValue(of(false));

component.getSidebarItems();
const menuItems = component.itemsSidebar;

expect(menuItems.length).toBe(2);
component.getSidebarItems().subscribe(() => {
const menuItems = component.itemsSidebar;
expect(menuItems.length).toBe(2);
});
});

it('when item is selected is should be set as active and the others as inactive', () => {
const route = 'time-clock';
router.navigate([route]);

component.itemsSidebar.filter(item => item.route === `/${route}`).map(item => {
component.itemsSidebar.filter((item) => item.route === `/${route}`).map((item) => {
expect(item.active).toBeTrue();
});
component.itemsSidebar.filter(item => item.route !== `/${route}`).map(item => {
component.itemsSidebar.filter((item) => item.route !== `/${route}`).map((item) => {
expect(item.active).toBeFalse();
});
});
Expand All @@ -101,5 +114,4 @@ describe('SidebarComponent', () => {

expect(itemsSidebar.length).toBe(0);
});

});
102 changes: 59 additions & 43 deletions src/app/modules/shared/components/sidebar/sidebar.component.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,47 @@
import {AzureAdB2CService} from 'src/app/modules/login/services/azure.ad.b2c.service';
import {Component, OnInit} from '@angular/core';
import {ItemSidebar} from './models/item-sidebar.model';
import {NavigationStart, Router} from '@angular/router';
import {Observable} from 'rxjs';
import {filter} from 'rxjs/operators';
import { AzureAdB2CService } from 'src/app/modules/login/services/azure.ad.b2c.service';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ItemSidebar } from './models/item-sidebar.model';
import { NavigationStart, Router } from '@angular/router';
import { Observable, of, Subscription } from 'rxjs';
import { filter, map, mergeMap } from 'rxjs/operators';
import { FeatureManagerService } from '../../feature-toggles/feature-toggle-manager.service';
import { UserInfoService } from 'src/app/modules/user/services/user-info.service';
import { FeatureSwitchGroupService } from '../../feature-toggles/switch-group/feature-switch-group.service';

@Component({
selector: 'app-sidebar',
templateUrl: './sidebar.component.html',
styleUrls: ['./sidebar.component.scss'],
})
export class SidebarComponent implements OnInit {

export class SidebarComponent implements OnInit, OnDestroy {
itemsSidebar: ItemSidebar[] = [];
navStart;
FTSwitchGroup$: Subscription;

constructor(
private azureAdB2CService: AzureAdB2CService,
private router: Router,
private userInfoService: UserInfoService,
private azureAdB2CService: AzureAdB2CService,
private featureManagerService: FeatureManagerService,
private featureSwitchGroup: FeatureSwitchGroupService
) {
this.navStart = this.router.events.pipe(
filter(evt => evt instanceof NavigationStart)
filter((evt) => evt instanceof NavigationStart)
) as Observable<NavigationStart>;
}

ngOnInit(): void {
this.toggleSideBar();
this.getSidebarItems();
this.FTSwitchGroup$ = this.getSidebarItems().subscribe();
this.toggleListTechnologies(this.itemsSidebar);
this.highlightMenuOption(this.router.routerState.snapshot.url);
this.navStart.subscribe(evt => {
this.navStart.subscribe((evt) => {
this.highlightMenuOption(evt.url);
});
}
ngOnDestroy(): void {
this.FTSwitchGroup$.unsubscribe();
}

toggleSideBar() {
$('#menu-toggle').on('click', (e) => {
Expand All @@ -43,42 +50,51 @@ export class SidebarComponent implements OnInit {
});
}

getSidebarItems() {
if (this.azureAdB2CService.isAdmin()) {
this.itemsSidebar = [
{route: '/time-clock', icon: 'fas fa-clock', text: 'Time Clock', active: false},
{route: '/time-entries', icon: 'fas fa-list-alt', text: 'Time Entries', active: false},
{route: '/reports', icon: 'fas fa-chart-pie', text: 'Reports', active: false},
{route: '/activities-management', icon: 'fas fa-file-alt', text: 'Activities', active: false},
{route: '/customers-management', icon: 'fas fa-user', text: 'Customers', active: false},
{route: '/users', icon: 'fas fa-user', text: 'Users', active: false},
];
} else {
this.itemsSidebar = [
{route: '/time-clock', icon: 'fas fa-clock', text: 'Time Clock', active: false},
{route: '/time-entries', icon: 'fas fa-list-alt', text: 'Time Entries', active: false},
];
}
getSidebarItems(): Observable<void> {
const isAdminBasedInRole = of(this.azureAdB2CService.isAdmin());
const isAdminBasedInGroup = this.userInfoService.isAdmin();
return this.featureSwitchGroup.isActivated().pipe(
mergeMap((enabled) => {
return enabled ? isAdminBasedInGroup : isAdminBasedInRole;
}),
map((isAdmin) => {
if (isAdmin) {
this.itemsSidebar = [
{ route: '/time-clock', icon: 'fas fa-clock', text: 'Time Clock', active: false },
{ route: '/time-entries', icon: 'fas fa-list-alt', text: 'Time Entries', active: false },
{ route: '/reports', icon: 'fas fa-chart-pie', text: 'Reports', active: false },
{ route: '/activities-management', icon: 'fas fa-file-alt', text: 'Activities', active: false },
{ route: '/customers-management', icon: 'fas fa-user', text: 'Customers', active: false },
{ route: '/users', icon: 'fas fa-user', text: 'Users', active: false },
];
} else {
this.itemsSidebar = [
{ route: '/time-clock', icon: 'fas fa-clock', text: 'Time Clock', active: false },
{ route: '/time-entries', icon: 'fas fa-list-alt', text: 'Time Entries', active: false },
];
}
})
);
}

toggleListTechnologies(itemsSidebar: ItemSidebar[]){
toggleListTechnologies(itemsSidebar: ItemSidebar[]) {
this.featureManagerService
.isToggleEnabledForUser('ui-list-technologies')
.subscribe((enabled) => {
if (enabled === true){
const listTechnologiesItem = {
route: '/technology-report',
icon: 'fas fa-user',
text: 'Technology Report',
active: false
};
itemsSidebar.push(listTechnologiesItem);
}
});
.isToggleEnabledForUser('ui-list-technologies')
.subscribe((enabled) => {
if (enabled === true) {
const listTechnologiesItem = {
route: '/technology-report',
icon: 'fas fa-user',
text: 'Technology Report',
active: false,
};
itemsSidebar.push(listTechnologiesItem);
}
});
}

highlightMenuOption(route) {
this.itemsSidebar.map(item => item.active = false);
this.itemsSidebar.filter(item => item.route === route).map(item => item.active = true);
this.itemsSidebar.map((item) => (item.active = false));
this.itemsSidebar.filter((item) => item.route === route).map((item) => (item.active = true));
}
}