Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
fix: TT-229 remove code from users-list.component & user ngrx store
  • Loading branch information
thegreatyamori committed Apr 28, 2021
commit a2d388cae4a368dfdc45e6d103bd040562455f8b
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<tr class="d-flex flex-wrap">
<th class="col-4">User Email</th>
<th class="col-5">Names</th>
<th class="col-3">{{ isUserGroupsToggleOn ? 'Groups' : 'Roles' }}</th>
<th class="col-3">Groups</th>
</tr>
</thead>
<app-loading-bar *ngIf="isLoading$ | async"></app-loading-bar>
Expand All @@ -19,35 +19,18 @@
<td class="col-4 text-break">{{ user.email }}</td>
<td class="col-5 text-break">{{ user.name }}</td>
<td class="col-3 text-center">
<div *ngIf="isUserGroupsToggleOn">
<ui-switch
size="small"
(change)="switchGroup('time-tracker-admin', user)"
[checked]="user.groups.includes('time-tracker-admin')"
></ui-switch>
admin
<ui-switch
size="small"
(change)="switchGroup('time-tracker-tester', user)"
[checked]="user.groups.includes('time-tracker-tester')"
></ui-switch>
test
</div>

<div *ngIf="!isUserGroupsToggleOn">
<ui-switch
size="small"
(change)="switchRole(user.id, user.roles, 'admin', 'time-tracker-admin')"
[checked]="user.roles.includes('time-tracker-admin')"
></ui-switch>
admin
<ui-switch
size="small"
(change)="switchRole(user.id, user.roles, 'test', 'time-tracker-tester')"
[checked]="user.roles.includes('time-tracker-tester')"
></ui-switch>
test
</div>
<ui-switch
size="small"
(change)="switchGroup('time-tracker-admin', user)"
[checked]="user.groups.includes('time-tracker-admin')"
></ui-switch>
admin
<ui-switch
size="small"
(change)="switchGroup('time-tracker-tester', user)"
[checked]="user.groups.includes('time-tracker-tester')"
></ui-switch>
test
</td>
</tr>
</tbody>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { FeatureManagerService } from 'src/app/modules/shared/feature-toggles/feature-toggle-manager.service';
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { MockStore, provideMockStore } from '@ngrx/store/testing';
import { NgxPaginationModule } from 'ngx-pagination';
Expand All @@ -7,28 +6,17 @@ import {
UserActionTypes,
UserState,
LoadUsers,
GrantRoleUser,
RevokeRoleUser,
AddUserToGroup,
RemoveUserFromGroup,
} from '../../store';
import { User } from '../../../user/models/user';
import { ActionsSubject } from '@ngrx/store';
import { DataTablesModule } from 'angular-datatables';
import { Observable, of } from 'rxjs';
import { FeatureToggleProvider } from 'src/app/modules/shared/feature-toggles/feature-toggle-provider.service';
import { AppConfigurationClient } from '@azure/app-configuration';
import { FeatureFilterProvider } from '../../../shared/feature-toggles/filters/feature-filter-provider.service';
import { AzureAdB2CService } from '../../../login/services/azure.ad.b2c.service';

describe('UsersListComponent', () => {
let component: UsersListComponent;
let fixture: ComponentFixture<UsersListComponent>;
let store: MockStore<UserState>;
const actionSub: ActionsSubject = new ActionsSubject();
const fakeAppConfigurationConnectionString = 'Endpoint=http://fake.foo;Id=fake.id;Secret=fake.secret';
let service: FeatureManagerService;
let fakeFeatureToggleProvider;

const state: UserState = {
data: [
Expand All @@ -48,19 +36,12 @@ describe('UsersListComponent', () => {

beforeEach(
waitForAsync(() => {
fakeFeatureToggleProvider = new FeatureToggleProvider(
new AppConfigurationClient(fakeAppConfigurationConnectionString),
new FeatureFilterProvider(new AzureAdB2CService())
);
service = new FeatureManagerService(fakeFeatureToggleProvider);

TestBed.configureTestingModule({
imports: [NgxPaginationModule, DataTablesModule],
declarations: [UsersListComponent],
providers: [
provideMockStore({ initialState: state }),
{ provide: ActionsSubject, useValue: actionSub },
{ provide: FeatureManagerService, useValue: service }
],
}).compileComponents();
})
Expand Down Expand Up @@ -98,27 +79,6 @@ describe('UsersListComponent', () => {
expect(component.users).toEqual(state.data);
});

const actionsParams = [
{ actionType: UserActionTypes.GRANT_USER_ROLE_SUCCESS },
{ actionType: UserActionTypes.REVOKE_USER_ROLE_SUCCESS },
];

actionsParams.map((param) => {
it(`When action ${param.actionType} is dispatched should triggered load Users action`, () => {
spyOn(store, 'dispatch');

const actionSubject = TestBed.inject(ActionsSubject) as ActionsSubject;
const action = {
type: param.actionType,
payload: state.data,
};

actionSubject.next(action);

expect(store.dispatch).toHaveBeenCalledWith(new LoadUsers());
});
});

const actionGroupParams = [
{ actionType: UserActionTypes.ADD_USER_TO_GROUP_SUCCESS },
{ actionType: UserActionTypes.REMOVE_USER_FROM_GROUP_SUCCESS },
Expand All @@ -140,26 +100,6 @@ describe('UsersListComponent', () => {
});
});

const grantRoleTypes = [
{ roleId: 'admin', roleValue: 'time-tracker-admin' },
{ roleId: 'test', roleValue: 'time-tracker-tester' },
];

grantRoleTypes.map((param) => {
it(`When user switchRole to ${param.roleId} and don't have any role, should grant ${param.roleValue} Role`, () => {
const roleId = param.roleId;
const roleValue = param.roleValue;
const userRoles = [];
const userId = 'userId';

spyOn(store, 'dispatch');

component.switchRole(userId, userRoles, roleId, roleValue);

expect(store.dispatch).toHaveBeenCalledWith(new GrantRoleUser(userId, roleId));
});
});

const AddGroupTypes = [
{ groupName: 'time-tracker-admin' },
{ groupName: 'time-tracker-tester' }
Expand All @@ -176,7 +116,7 @@ describe('UsersListComponent', () => {
id: 'id',
tenant_id: 'tenant id',
deleted: 'delete',
} ;
};

spyOn(store, 'dispatch');

Expand All @@ -186,26 +126,6 @@ describe('UsersListComponent', () => {
});
});

const revokeRoleTypes = [
{ roleId: 'admin', roleValue: 'time-tracker-admin', userRoles: ['time-tracker-admin'] },
{ roleId: 'test', roleValue: 'time-tracker-tester', userRoles: ['time-tracker-tester'] },
];

revokeRoleTypes.map((param) => {
it(`When user switchRole to ${param.roleId} and have that rol asigned, should revoke ${param.roleValue} Role`, () => {
const roleId = param.roleId;
const roleValue = param.roleValue;
const userRoles = param.userRoles;
const userId = 'userId';

spyOn(store, 'dispatch');

component.switchRole(userId, userRoles, roleId, roleValue);

expect(store.dispatch).toHaveBeenCalledWith(new RevokeRoleUser(userId, roleId));
});
});

const removeGroupTypes = [
{ groupName: 'time-tracker-admin', userGroups: ['time-tracker-admin'] },
{ groupName: 'time-tracker-tester', userGroups: ['time-tracker-tester'] },
Expand All @@ -222,8 +142,7 @@ describe('UsersListComponent', () => {
id: 'id',
tenant_id: 'tenant id',
deleted: 'delete',
} ;

};

spyOn(store, 'dispatch');

Expand All @@ -233,20 +152,6 @@ describe('UsersListComponent', () => {
});
});

it('on success load users, the data of roles should be an array', () => {
const actionSubject = TestBed.inject(ActionsSubject) as ActionsSubject;
const action = {
type: UserActionTypes.LOAD_USERS_SUCCESS,
payload: state.data,
};

actionSubject.next(action);

component.users.map((user) => {
expect(user.roles).toEqual(['admin', 'test']);
});
});

it('on success load users, the data of groups should be an array', () => {
const actionSubject = TestBed.inject(ActionsSubject) as ActionsSubject;
const action = {
Expand Down Expand Up @@ -274,27 +179,6 @@ describe('UsersListComponent', () => {
expect(component.dtElement.dtInstance.then).toHaveBeenCalled();
});

it('When Component is created, should call the feature toggle method', () => {
spyOn(component, 'isFeatureToggleActivated').and.returnValue(of(true));

component.ngOnInit();

expect(component.isFeatureToggleActivated).toHaveBeenCalled();
expect(component.isUserGroupsToggleOn).toBe(true);
});

const toggleValues = [true, false];
toggleValues.map((toggleValue) => {
it(`when FeatureToggle is ${toggleValue} should return ${toggleValue}`, () => {
spyOn(service, 'isToggleEnabledForUser').and.returnValue(of(toggleValue));

const isFeatureToggleActivated: Observable<boolean> = component.isFeatureToggleActivated();

expect(service.isToggleEnabledForUser).toHaveBeenCalled();
isFeatureToggleActivated.subscribe((value) => expect(value).toEqual(toggleValue));
});
});

afterEach(() => {
component.dtTrigger.unsubscribe();
component.loadUsersSubscription.unsubscribe();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@ import { AfterViewInit, Component, OnDestroy, OnInit, ViewChild } from '@angular
import { ActionsSubject, select, Store, Action } from '@ngrx/store';
import { DataTableDirective } from 'angular-datatables';
import { Observable, Subject, Subscription } from 'rxjs';
import { delay, filter, map } from 'rxjs/operators';
import { FeatureManagerService } from 'src/app/modules/shared/feature-toggles/feature-toggle-manager.service';
import { delay, filter } from 'rxjs/operators';
import { User } from '../../models/users';
import {
GrantRoleUser,
LoadUsers,
RevokeRoleUser,
UserActionTypes,
AddUserToGroup,
RemoveUserFromGroup,
Expand All @@ -30,13 +27,10 @@ export class UsersListComponent implements OnInit, OnDestroy, AfterViewInit {
dtElement: DataTableDirective;
dtOptions: any = {};
switchGroupsSubscription: Subscription;
isEnableToggleSubscription: Subscription;
isUserGroupsToggleOn: boolean;

constructor(
private store: Store<User>,
private actionsSubject$: ActionsSubject,
private featureManagerService: FeatureManagerService
) {
this.isLoading$ = store.pipe(delay(0), select(getIsLoading));
}
Expand All @@ -50,25 +44,9 @@ export class UsersListComponent implements OnInit, OnDestroy, AfterViewInit {
this.rerenderDataTable();
});

this.isEnableToggleSubscription = this.isFeatureToggleActivated().subscribe((flag) => {
this.isUserGroupsToggleOn = flag;
});

this.switchGroupsSubscription = this.filterUserGroup().subscribe((action) => {
this.store.dispatch(new LoadUsers());
});

this.switchRoleSubscription = this.actionsSubject$
.pipe(
filter(
(action: any) =>
action.type === UserActionTypes.GRANT_USER_ROLE_SUCCESS ||
action.type === UserActionTypes.REVOKE_USER_ROLE_SUCCESS
)
)
.subscribe((action) => {
this.store.dispatch(new LoadUsers());
});
}

ngAfterViewInit(): void {
Expand All @@ -78,7 +56,6 @@ export class UsersListComponent implements OnInit, OnDestroy, AfterViewInit {
ngOnDestroy() {
this.loadUsersSubscription.unsubscribe();
this.dtTrigger.unsubscribe();
this.isEnableToggleSubscription.unsubscribe();
}

private rerenderDataTable(): void {
Expand All @@ -92,12 +69,6 @@ export class UsersListComponent implements OnInit, OnDestroy, AfterViewInit {
}
}

switchRole(userId: string, userRoles: string[], roleId: string, roleValue: string) {
userRoles.includes(roleValue)
? this.store.dispatch(new RevokeRoleUser(userId, roleId))
: this.store.dispatch(new GrantRoleUser(userId, roleId));
}

switchGroup(groupName: string, user: User): void {
this.store.dispatch(
user.groups.includes(groupName)
Expand All @@ -106,11 +77,6 @@ export class UsersListComponent implements OnInit, OnDestroy, AfterViewInit {
);
}

isFeatureToggleActivated(): Observable<boolean> {
return this.featureManagerService.isToggleEnabledForUser('switch-group')
.pipe(map((enabled: boolean) => enabled));
}

filterUserGroup(): Observable<Action> {
return this.actionsSubject$.pipe(
filter(
Expand Down
36 changes: 0 additions & 36 deletions src/app/modules/users/store/user.actions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,42 +17,6 @@ describe('UserActions', () => {
expect(action.type).toEqual(actions.UserActionTypes.LOAD_USERS_FAIL);
});

it('GrantRoleUser type is UserActionTypes.GRANT_USER_ROLE', () => {
const UserId = 'UserId';
const RoleId = 'RoleId';
const action = new actions.GrantRoleUser(UserId, RoleId);
expect(action.type).toEqual(actions.UserActionTypes.GRANT_USER_ROLE);
});

it('GrantRoleUserSuccess type is UserActionTypes.GRANT_USER_ROLE_SUCCESS', () => {
const payload: User = { id: 'id', email: 'email', name: 'name' };
const action = new actions.GrantRoleUserSuccess(payload);
expect(action.type).toEqual(actions.UserActionTypes.GRANT_USER_ROLE_SUCCESS);
});

it('GrantRoleUserFail type is UserActionTypes.GRANT_USER_ROLE_FAIL', () => {
const action = new actions.GrantRoleUserFail('error');
expect(action.type).toEqual(actions.UserActionTypes.GRANT_USER_ROLE_FAIL);
});

it('RevokeRoleUser type is UserActionTypes.REVOKE_USER_ROLE', () => {
const UserId = 'UserId';
const RoleId = 'RoleId';
const action = new actions.RevokeRoleUser(UserId, RoleId);
expect(action.type).toEqual(actions.UserActionTypes.REVOKE_USER_ROLE);
});

it('RevokeRoleUserSuccess type is UserActionTypes.REVOKE_USER_ROLE_SUCCESS', () => {
const payload: User = { id: 'id', email: 'email', name: 'name' };
const action = new actions.RevokeRoleUserSuccess(payload);
expect(action.type).toEqual(actions.UserActionTypes.REVOKE_USER_ROLE_SUCCESS);
});

it('RevokeRoleUserFail type is UserActionTypes.REVOKE_USER_ROLE_FAIL', () => {
const action = new actions.RevokeRoleUserFail('error');
expect(action.type).toEqual(actions.UserActionTypes.REVOKE_USER_ROLE_FAIL);
});

it('AddUserToGroup type is UserActionTypes.ADD_USER_TO_GROUP', () => {
const userId = 'userId';
const groupName = 'groupName';
Expand Down
Loading