Skip to content

Commit e1e94f1

Browse files
feat: TT-188 add ngrx flow & test
1 parent d9fd3d6 commit e1e94f1

File tree

8 files changed

+306
-9
lines changed

8 files changed

+306
-9
lines changed

src/app/modules/user/store/user.effects.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export class UserEffects {
1414
loadUserInfo$: Observable<Action> = this.actions$.pipe(
1515
ofType(actions.UserActionTypes.LOAD_USER),
1616
map((action: actions.LoadUser) => action.userId),
17-
mergeMap((userId) =>
17+
mergeMap((userId: string) =>
1818
this.userService.loadUser(userId).pipe(
1919
map((response) => new actions.LoadUserSuccess(response)),
2020
catchError((error) => of(new actions.LoadUserFail(error)))

src/app/modules/users/models/users.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,3 @@ export interface User {
77
tenant_id?: string;
88
deleted?: string;
99
}
10-
11-
export interface UserState extends User {
12-
isLoading: boolean;
13-
error: string;
14-
}

src/app/modules/users/store/user.actions.spec.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,46 @@ describe('UserActions', () => {
5252
const action = new actions.RevokeRoleUserFail('error');
5353
expect(action.type).toEqual(actions.UserActionTypes.REVOKE_USER_ROLE_FAIL);
5454
});
55+
56+
it('AddGroupToUser type is UserActionTypes.ADD_GROUP_TO_USER', () => {
57+
const userId = 'userId';
58+
const groupName = 'groupName';
59+
const action = new actions.AddGroupToUser(userId, groupName);
60+
61+
expect(action.type).toEqual(actions.UserActionTypes.ADD_GROUP_TO_USER);
62+
});
63+
64+
it('AddGroupToUserSuccess type is UserActionTypes.ADD_GROUP_TO_USER_SUCCESS', () => {
65+
const payload: User = { id: 'id', email: 'email', name: 'name' };
66+
const action = new actions.AddGroupToUserSuccess(payload);
67+
68+
expect(action.type).toEqual(actions.UserActionTypes.ADD_GROUP_TO_USER_SUCCESS);
69+
});
70+
71+
it('AddGroupToUserFail type is UserActionTypes.ADD_GROUP_TO_USER_FAIL', () => {
72+
const action = new actions.AddGroupToUserFail('error');
73+
74+
expect(action.type).toEqual(actions.UserActionTypes.ADD_GROUP_TO_USER_FAIL);
75+
});
76+
77+
it('RemoveGroupToUser type is UserActionTypes.REMOVE_GROUP_TO_USER', () => {
78+
const userId = 'userId';
79+
const groupName = 'groupName';
80+
const action = new actions.RemoveGroupToUser(userId, groupName);
81+
82+
expect(action.type).toEqual(actions.UserActionTypes.REMOVE_GROUP_TO_USER);
83+
});
84+
85+
it('RemoveGroupToUserSuccess type is UserActionTypes.REMOVE_GROUP_TO_USER_SUCCESS', () => {
86+
const payload: User = { id: 'id', email: 'email', name: 'name' };
87+
const action = new actions.RemoveGroupToUserSuccess(payload);
88+
89+
expect(action.type).toEqual(actions.UserActionTypes.REMOVE_GROUP_TO_USER_SUCCESS);
90+
});
91+
92+
it('RemoveGroupToUserFail type is UserActionTypes.REMOVE_GROUP_TO_USER_FAIL', () => {
93+
const action = new actions.RemoveGroupToUserFail('error');
94+
95+
expect(action.type).toEqual(actions.UserActionTypes.REMOVE_GROUP_TO_USER_FAIL);
96+
});
5597
});

src/app/modules/users/store/user.actions.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ export enum UserActionTypes {
1111
REVOKE_USER_ROLE = '[User] REVOKE_USER_ROLE',
1212
REVOKE_USER_ROLE_SUCCESS = '[User] REVOKE_USER_ROLE_SUCCESS',
1313
REVOKE_USER_ROLE_FAIL = '[User] REVOKE_USER_ROLE_FAIL',
14+
ADD_GROUP_TO_USER = '[User] ADD_GROUP_TO_USER',
15+
ADD_GROUP_TO_USER_SUCCESS = '[User] ADD_GROUP_TO_USER_SUCCESS',
16+
ADD_GROUP_TO_USER_FAIL = '[User] ADD_GROUP_TO_USER_FAIL',
17+
REMOVE_GROUP_TO_USER = '[User] REMOVE_GROUP_TO_USER',
18+
REMOVE_GROUP_TO_USER_SUCCESS = '[User] REMOVE_GROUP_TO_USER_SUCCESS',
19+
REMOVE_GROUP_TO_USER_FAIL = '[User] REMOVE_GROUP_TO_USER_FAIL',
1420
DEFAULT_USER = '[USER] DEFAULT_USER',
1521
}
1622

@@ -57,6 +63,37 @@ export class RevokeRoleUserFail implements Action {
5763
public readonly type = UserActionTypes.REVOKE_USER_ROLE_FAIL;
5864
constructor(public error: string) {}
5965
}
66+
67+
export class AddGroupToUser implements Action {
68+
public readonly type = UserActionTypes.ADD_GROUP_TO_USER;
69+
constructor(public userId: string, public groupName: string) {}
70+
}
71+
72+
export class AddGroupToUserSuccess implements Action {
73+
public readonly type = UserActionTypes.ADD_GROUP_TO_USER_SUCCESS;
74+
constructor(readonly payload: User) {}
75+
}
76+
77+
export class AddGroupToUserFail implements Action {
78+
public readonly type = UserActionTypes.ADD_GROUP_TO_USER_FAIL;
79+
constructor(public error: string) {}
80+
}
81+
82+
export class RemoveGroupToUser implements Action {
83+
public readonly type = UserActionTypes.REMOVE_GROUP_TO_USER;
84+
constructor(public userId: string, public groupName: string) {}
85+
}
86+
87+
export class RemoveGroupToUserSuccess implements Action {
88+
public readonly type = UserActionTypes.REMOVE_GROUP_TO_USER_SUCCESS;
89+
constructor(readonly payload: User) {}
90+
}
91+
92+
export class RemoveGroupToUserFail implements Action {
93+
public readonly type = UserActionTypes.REMOVE_GROUP_TO_USER_FAIL;
94+
constructor(public error: string) {}
95+
}
96+
6097
export class DefaultUser implements Action {
6198
public readonly type = UserActionTypes.DEFAULT_USER;
6299
}
@@ -71,4 +108,10 @@ export type UserActions =
71108
| GrantRoleUserFail
72109
| RevokeRoleUser
73110
| RevokeRoleUserSuccess
74-
| RevokeRoleUserFail;
111+
| RevokeRoleUserFail
112+
| AddGroupToUser
113+
| AddGroupToUserSuccess
114+
| AddGroupToUserFail
115+
| RemoveGroupToUser
116+
| RemoveGroupToUserSuccess
117+
| RemoveGroupToUserFail;

src/app/modules/users/store/user.effects.spec.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,76 @@ describe('UserEffects', () => {
105105
expect(action.type).toEqual(UserActionTypes.REVOKE_USER_ROLE_FAIL);
106106
});
107107
});
108+
109+
it('action type is ADD_GROUP_TO_USER_SUCCESS when service is executed sucessfully', async () => {
110+
const userId = 'userId';
111+
const groupName = 'groupName';
112+
actions$ = of({
113+
type: UserActionTypes.ADD_GROUP_TO_USER,
114+
userId,
115+
groupName,
116+
});
117+
118+
spyOn(toastrService, 'success');
119+
spyOn(service, 'addGroupToUser').and.returnValue(of(user));
120+
121+
effects.addGroupToUser$.subscribe((action) => {
122+
expect(toastrService.success).toHaveBeenCalledWith('Add group to a user success');
123+
expect(action.type).toEqual(UserActionTypes.ADD_GROUP_TO_USER_SUCCESS);
124+
});
125+
});
126+
127+
it('action type is ADD_GROUP_TO_USER_FAIL when service is executed and fail', async () => {
128+
const userId = 'userId';
129+
const groupName = 'groupName';
130+
actions$ = of({
131+
type: UserActionTypes.ADD_GROUP_TO_USER,
132+
userId,
133+
groupName,
134+
});
135+
136+
spyOn(toastrService, 'error');
137+
spyOn(service, 'addGroupToUser').and.returnValue(throwError({ error: { message: 'error' } }));
138+
139+
effects.addGroupToUser$.subscribe((action) => {
140+
expect(toastrService.error).toHaveBeenCalled();
141+
expect(action.type).toEqual(UserActionTypes.ADD_GROUP_TO_USER_FAIL);
142+
});
143+
});
144+
145+
it('action type is REMOVE_GROUP_TO_USER_SUCCESS when service is executed succesfully', async () => {
146+
const userId = 'userId';
147+
const groupName = 'groupName';
148+
actions$ = of({
149+
type: UserActionTypes.REMOVE_GROUP_TO_USER,
150+
userId,
151+
groupName,
152+
});
153+
154+
spyOn(toastrService, 'success');
155+
spyOn(service, 'removeGroupToUser').and.returnValue(of(user));
156+
157+
effects.removeGroupToUser$.subscribe((action) => {
158+
expect(toastrService.success).toHaveBeenCalledWith('Remove group to a user success');
159+
expect(action.type).toEqual(UserActionTypes.REMOVE_GROUP_TO_USER_SUCCESS);
160+
});
161+
});
162+
163+
it('action type is REMOVE_GROUP_TO_USER_FAIL when service is executed succesfully', async () => {
164+
const userId = 'userId';
165+
const groupName = 'groupName';
166+
actions$ = of({
167+
type: UserActionTypes.REMOVE_GROUP_TO_USER,
168+
userId,
169+
groupName,
170+
});
171+
172+
spyOn(toastrService, 'error');
173+
spyOn(service, 'removeGroupToUser').and.returnValue(throwError({ error: { message: 'error' } }));
174+
175+
effects.removeGroupToUser$.subscribe((action) => {
176+
expect(toastrService.error).toHaveBeenCalled();
177+
expect(action.type).toEqual(UserActionTypes.REMOVE_GROUP_TO_USER_FAIL);
178+
});
179+
});
108180
});

src/app/modules/users/store/user.effects.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,40 @@ export class UserEffects {
6363
)
6464
)
6565
);
66+
67+
@Effect()
68+
addGroupToUser$: Observable<Action> = this.actions$.pipe(
69+
ofType(actions.UserActionTypes.ADD_GROUP_TO_USER),
70+
map((action: actions.AddGroupToUser) => action),
71+
mergeMap((action) =>
72+
this.userService.addGroupToUser(action.userId, action.groupName).pipe(
73+
map((response) => {
74+
this.toastrService.success('Add group to a user success');
75+
return new actions.AddGroupToUserSuccess(response);
76+
}),
77+
catchError((error) => {
78+
this.toastrService.error(error.error.message);
79+
return of(new actions.AddGroupToUserFail(error));
80+
})
81+
)
82+
)
83+
);
84+
85+
@Effect()
86+
removeGroupToUser$: Observable<Action> = this.actions$.pipe(
87+
ofType(actions.UserActionTypes.REMOVE_GROUP_TO_USER),
88+
map((action: actions.RemoveGroupToUser) => action),
89+
mergeMap((action) =>
90+
this.userService.removeGroupToUser(action.userId, action.groupName).pipe(
91+
map((response) => {
92+
this.toastrService.success('Remove group to a user success');
93+
return new actions.RemoveGroupToUserSuccess(response);
94+
}),
95+
catchError((error) => {
96+
this.toastrService.error(error.error.message);
97+
return of(new actions.RemoveGroupToUserFail(error));
98+
})
99+
)
100+
)
101+
);
66102
}

src/app/modules/users/store/user.reducer.spec.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,70 @@ describe('userReducer', () => {
9393
expect(state.isLoading).toEqual(false);
9494
});
9595

96+
it('on AddGroupToUser, isLoading is true', () => {
97+
const userId = 'userId';
98+
const groupName = 'groupName';
99+
const action = new actions.AddGroupToUser(userId, groupName);
100+
const state = userReducer(initialState, action);
101+
102+
expect(state.isLoading).toEqual(true);
103+
});
104+
105+
it('on AddGroupToUserSuccess, user groups should change', () => {
106+
const currentState: UserState = {
107+
data: [{ id: 'id', name: 'name', email: 'email', groups: null }],
108+
isLoading: false,
109+
message: '',
110+
};
111+
const userWithGroupAdded: User = { id: 'id', name: 'name', email: 'email', groups: ['group'] };
112+
const action = new actions.AddGroupToUserSuccess(userWithGroupAdded);
113+
const state = userReducer(currentState, action);
114+
115+
expect(state.data).toEqual([userWithGroupAdded]);
116+
expect(state.isLoading).toEqual(false);
117+
expect(state.message).toEqual('Add group to a user success');
118+
});
119+
120+
it('on AddGroupToUserFail, should show a message with an error message', () => {
121+
const action = new actions.AddGroupToUserFail('error');
122+
const state = userReducer(initialState, action);
123+
124+
expect(state.message).toEqual('Something went wrong adding group to a user');
125+
expect(state.isLoading).toEqual(false);
126+
});
127+
128+
it('on RemoveGroupToUser, isLoading is true', () => {
129+
const userId = 'userId';
130+
const groupName = 'groupName';
131+
const action = new actions.RemoveGroupToUser(userId, groupName);
132+
const state = userReducer(initialState, action);
133+
134+
expect(state.isLoading).toEqual(true);
135+
});
136+
137+
it('on RemoveGroupToUserSuccess, user groups should change', () => {
138+
const currentState: UserState = {
139+
data: [{ id: 'id', name: 'name', email: 'email', groups: ['group'] }],
140+
isLoading: false,
141+
message: '',
142+
};
143+
const userWithGroupRemoved: User = { id: 'id', name: 'name', email: 'email', groups: null };
144+
const action = new actions.RemoveGroupToUserSuccess(userWithGroupRemoved);
145+
const state = userReducer(currentState, action);
146+
147+
expect(state.data).toEqual([userWithGroupRemoved]);
148+
expect(state.isLoading).toEqual(false);
149+
expect(state.message).toEqual('Remove group to a user success');
150+
});
151+
152+
it('on RemoveGroupToUserFail, should show a message with an error message', () => {
153+
const action = new actions.RemoveGroupToUserFail('error');
154+
const state = userReducer(initialState, action);
155+
156+
expect(state.message).toEqual('Something went wrong removing group to a user');
157+
expect(state.isLoading).toEqual(false);
158+
});
159+
96160
it('on Default, ', () => {
97161
const action = new actions.DefaultUser();
98162
const state = userReducer(initialState, action);

src/app/modules/users/store/user.reducers.ts

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export const userReducer = (state: UserState = initialState, action: UserActions
3737
message: action.error,
3838
};
3939
}
40+
4041
case UserActionTypes.GRANT_USER_ROLE: {
4142
return {
4243
...state,
@@ -53,7 +54,6 @@ export const userReducer = (state: UserState = initialState, action: UserActions
5354
message: 'Grant User Role Success',
5455
};
5556
}
56-
5757
case UserActionTypes.GRANT_USER_ROLE_FAIL: {
5858
return {
5959
...state,
@@ -79,7 +79,6 @@ export const userReducer = (state: UserState = initialState, action: UserActions
7979
message: 'Revoke User Role Success',
8080
};
8181
}
82-
8382
case UserActionTypes.REVOKE_USER_ROLE_FAIL: {
8483
return {
8584
...state,
@@ -88,6 +87,52 @@ export const userReducer = (state: UserState = initialState, action: UserActions
8887
message: 'Something went wrong revoking user role',
8988
};
9089
}
90+
91+
case UserActionTypes.ADD_GROUP_TO_USER: {
92+
return {
93+
...state,
94+
isLoading: true,
95+
};
96+
}
97+
case UserActionTypes.ADD_GROUP_TO_USER_SUCCESS: {
98+
const index = userData.findIndex((user) => user.id === action.payload.id);
99+
userData[index] = action.payload;
100+
return {
101+
data: userData,
102+
isLoading: false,
103+
message: 'Add group to a user success',
104+
};
105+
}
106+
case UserActionTypes.ADD_GROUP_TO_USER_FAIL: {
107+
return {
108+
...state,
109+
isLoading: false,
110+
message: 'Something went wrong adding group to a user',
111+
};
112+
}
113+
114+
case UserActionTypes.REMOVE_GROUP_TO_USER: {
115+
return {
116+
...state,
117+
isLoading: true,
118+
};
119+
}
120+
case UserActionTypes.REMOVE_GROUP_TO_USER_SUCCESS: {
121+
const index = userData.findIndex((user) => user.id === action.payload.id);
122+
userData[index] = action.payload;
123+
return {
124+
data: userData,
125+
isLoading: false,
126+
message: 'Remove group to a user success',
127+
};
128+
}
129+
case UserActionTypes.REMOVE_GROUP_TO_USER_FAIL: {
130+
return {
131+
...state,
132+
isLoading: false,
133+
message: 'Something went wrong removing group to a user',
134+
};
135+
}
91136
default:
92137
return state;
93138
}

0 commit comments

Comments
 (0)