Skip to content

Commit 02cb07b

Browse files
authored
refactor: TT-327 Replace recently projects (#753)
* refactor: TT-327 Replace recently projects * refactor: TT-327 Solving code smells from sonarcloud Co-authored-by: Andrés Soto
1 parent f8274ae commit 02cb07b

22 files changed

+297
-222
lines changed

src/app/modules/customer-management/components/projects/components/create-project/create-project.component.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ describe('InputProjectComponent', () => {
1717
const state = {
1818
projects: [{ id: '', name: '', project_type_id: '' }],
1919
customerProjects: [{ id: '', name: '', project_type_id: '' }],
20+
recentProjects: [],
2021
isLoading: false,
2122
message: '',
2223
projectToEdit: undefined,

src/app/modules/customer-management/components/projects/components/project-list/project-list.component.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ describe('ProjectListComponent', () => {
2323
const state: ProjectState = {
2424
projects: [project],
2525
customerProjects: [project],
26+
recentProjects: [],
2627
isLoading: false,
2728
message: '',
2829
projectToEdit: undefined,

src/app/modules/customer-management/components/projects/components/services/project.service.spec.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,16 @@ describe('ProjectService', () => {
5959
getProjectsRequest.flush(projectsList);
6060
});
6161

62+
it('recent projects are read using GET from url/recent', () => {
63+
const projectsFoundSize = projectsList.length;
64+
service.getRecentProjects().subscribe((projectsInResponse) => {
65+
expect(projectsInResponse.length).toBe(projectsFoundSize);
66+
});
67+
const getProjectsRequest = httpMock.expectOne(`${service.url}/recent`);
68+
expect(getProjectsRequest.request.method).toBe('GET');
69+
getProjectsRequest.flush(projectsList);
70+
});
71+
6272
it('create project using POST from url', () => {
6373
const project: Project[] = [{ id: '1', name: 'ccc', description: 'xxx', project_type_id: '123' }];
6474
service.url = 'projects';

src/app/modules/customer-management/components/projects/components/services/project.service.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ export class ProjectService {
2222
return this.http.get<Project[]>(this.url);
2323
}
2424

25+
getRecentProjects(): Observable<Project[]> {
26+
return this.http.get<Project[]>(`${this.url}/recent`);
27+
}
28+
2529
createProject(projectData): Observable<any> {
2630
return this.http.post<Project[]>(this.url, projectData);
2731
}

src/app/modules/customer-management/components/projects/components/store/project.actions.spec.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@ describe('Actions for Projects', () => {
2727
expect(LoadCustomerProjectsFail.type).toEqual(actions.ProjectActionTypes.LOAD_CUSTOMER_PROJECTS_FAIL);
2828
});
2929

30+
it('LoadRecentProjectsSuccess type is ProjectActionTypes.LOAD_RECENT_PROJECTS_SUCCESS', () => {
31+
const action = new actions.LoadRecentProjectsSuccess([]);
32+
expect(action.type).toEqual(actions.ProjectActionTypes.LOAD_RECENT_PROJECTS_SUCCESS);
33+
});
34+
35+
it('LoadRecentProjectsFail type is ProjectActionTypes.LOAD_RECENT_PROJECTS_FAIL', () => {
36+
const action = new actions.LoadRecentProjectsFail('error');
37+
expect(action.type).toEqual(actions.ProjectActionTypes.LOAD_RECENT_PROJECTS_FAIL);
38+
});
39+
3040
it('CreateProjectSuccess type is ProjectActionTypes.CREATE_PROJECT_SUCCESS', () => {
3141
const createProjectSuccess = new actions.CreateProjectSuccess({
3242
id: '1',

src/app/modules/customer-management/components/projects/components/store/project.actions.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ export enum ProjectActionTypes {
88
LOAD_CUSTOMER_PROJECTS = '[Projects] LOAD_CUSTOMER_PROJECTS',
99
LOAD_CUSTOMER_PROJECTS_SUCCESS = '[Projects] LOAD_CUSTOMER_PROJECTS_SUCCESS',
1010
LOAD_CUSTOMER_PROJECTS_FAIL = '[Projects] LOAD_CUSTOMER_PROJECTS_FAIL',
11+
LOAD_RECENT_PROJECTS_SUCCESS = '[Projects] LOAD_RECENT_PROJECTS_SUCCESS',
12+
LOAD_RECENT_PROJECTS_FAIL = '[Projects] LOAD_RECENT_PROJECTS_FAIL',
1113
CREATE_PROJECT = '[Projects] CREATE_PROJECT',
1214
CREATE_PROJECT_SUCCESS = '[Projects] CREATE_PROJECT_SUCCESS',
1315
CREATE_PROJECT_FAIL = '[Projects] CREATE_PROJECT_FAIL',
@@ -60,6 +62,16 @@ export class LoadCustomerProjectsFail implements Action {
6062
constructor(public error: string) {}
6163
}
6264

65+
export class LoadRecentProjectsSuccess implements Action {
66+
readonly type = ProjectActionTypes.LOAD_RECENT_PROJECTS_SUCCESS;
67+
constructor(readonly payload: Project[]) {}
68+
}
69+
70+
export class LoadRecentProjectsFail implements Action {
71+
public readonly type = ProjectActionTypes.LOAD_RECENT_PROJECTS_FAIL;
72+
constructor(public error: string) {}
73+
}
74+
6375
export class CreateProject implements Action {
6476
public readonly type = ProjectActionTypes.CREATE_PROJECT;
6577

@@ -150,6 +162,8 @@ export type ProjectActions =
150162
| LoadCustomerProjects
151163
| LoadCustomerProjectsSuccess
152164
| LoadCustomerProjectsFail
165+
| LoadRecentProjectsSuccess
166+
| LoadRecentProjectsFail
153167
| CreateProject
154168
| CreateProjectSuccess
155169
| CreateProjectFail

src/app/modules/customer-management/components/projects/components/store/project.effects.spec.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,28 @@ describe('ProjectEffects', () => {
5555
});
5656
});
5757

58+
it('action type is LOAD_RECENT_PROJECTS_SUCCESS when service is executed sucessfully', async () => {
59+
actions$ = of({ type: ProjectActionTypes.LOAD_PROJECTS });
60+
const serviceSpy = spyOn(service, 'getRecentProjects');
61+
serviceSpy.and.returnValue(of(projects));
62+
63+
effects.loadRecentProjects$.subscribe((action) => {
64+
expect(action.type).toEqual(ProjectActionTypes.LOAD_RECENT_PROJECTS_SUCCESS);
65+
});
66+
});
67+
68+
it('action type is LOAD_RECENT_PROJECTS_FAIL when service fail in execution', async () => {
69+
actions$ = of({ type: ProjectActionTypes.LOAD_PROJECTS });
70+
const serviceSpy = spyOn(service, 'getRecentProjects');
71+
serviceSpy.and.returnValue(throwError({ error: { message: 'fail!' } }));
72+
spyOn(toastrService, 'error');
73+
74+
effects.loadRecentProjects$.subscribe((action) => {
75+
expect(toastrService.error).toHaveBeenCalled();
76+
expect(action.type).toEqual(ProjectActionTypes.LOAD_RECENT_PROJECTS_FAIL);
77+
});
78+
});
79+
5880
it('action type is UPDATE_PROJECT_SUCCESS when service is executed sucessfully', async () => {
5981
actions$ = of({ type: ProjectActionTypes.UPDATE_PROJECT, project });
6082
spyOn(toastrService, 'success');

src/app/modules/customer-management/components/projects/components/store/project.effects.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,22 @@ export class ProjectEffects {
4949
)
5050
);
5151

52+
@Effect()
53+
loadRecentProjects$: Observable<Action> = this.actions$.pipe(
54+
ofType(actions.ProjectActionTypes.LOAD_PROJECTS),
55+
mergeMap(() =>
56+
this.projectService.getRecentProjects().pipe(
57+
map((projects) => {
58+
return new actions.LoadRecentProjectsSuccess(projects);
59+
}),
60+
catchError((error) => {
61+
this.toastrService.error(error.error.message);
62+
return of(new actions.LoadRecentProjectsFail(error));
63+
})
64+
)
65+
)
66+
);
67+
5268
@Effect()
5369
createProject$: Observable<Action> = this.actions$.pipe(
5470
ofType(actions.ProjectActionTypes.CREATE_PROJECT),

src/app/modules/customer-management/components/projects/components/store/project.reducer.spec.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import { projectReducer, ProjectState } from './project.reducer';
55
describe('projectReducer', () => {
66
const initialState: ProjectState = {
77
projects: [{ id: 'id', name: 'name', project_type_id: '', status: 'inactive' }],
8-
customerProjects: [], isLoading: false, message: '', projectToEdit: undefined
8+
customerProjects: [],
9+
recentProjects: [],
10+
isLoading: false, message: '', projectToEdit: undefined
911
};
1012
const archivedProject: Project = { id: '1', name: 'aaa', description: 'bbb', project_type_id: '123', status: 'inactive' };
1113
const project: Project = { id: '1', name: 'aaa', description: 'bbb', project_type_id: '123', status: 'active' };
@@ -38,6 +40,23 @@ describe('projectReducer', () => {
3840
expect(state.customerProjects).toEqual([]);
3941
});
4042

43+
it('on LoadRecentProjectsSuccess, projectsFound are saved in the store', () => {
44+
const projectsFound: Project[] = [{ id: '1', name: 'abc', description: 'xxx', status: 'active' }];
45+
const newState = initialState;
46+
newState.recentProjects = projectsFound;
47+
const action = new actions.LoadRecentProjectsSuccess(projectsFound);
48+
const state = projectReducer(initialState, action);
49+
expect(state).toEqual(newState);
50+
});
51+
52+
it('on LoadRecentProjectsFail, recentProjects equal []', () => {
53+
const newState = initialState;
54+
newState.recentProjects = [];
55+
const action = new actions.LoadRecentProjectsFail('error');
56+
const state = projectReducer(initialState, action);
57+
expect(state).toEqual(newState);
58+
});
59+
4160
it('on CreateProject, isLoading is true', () => {
4261
const action = new actions.CreateProject(project);
4362
const state = projectReducer(initialState, action);
@@ -74,6 +93,7 @@ describe('projectReducer', () => {
7493
const currentState: ProjectState = {
7594
projects: [project],
7695
customerProjects: [project],
96+
recentProjects: [project],
7797
isLoading: false,
7898
message: '',
7999
projectToEdit: project,
@@ -124,6 +144,7 @@ describe('projectReducer', () => {
124144
const currentState: ProjectState = {
125145
projects: [project],
126146
customerProjects: [project],
147+
recentProjects: [project],
127148
isLoading: false,
128149
message: '',
129150
projectToEdit: undefined,
@@ -158,6 +179,7 @@ describe('projectReducer', () => {
158179
const currentState: ProjectState = {
159180
projects: [project],
160181
customerProjects: [archivedProject],
182+
recentProjects: [project],
161183
isLoading: false,
162184
message: '',
163185
projectToEdit: project,

src/app/modules/customer-management/components/projects/components/store/project.reducer.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Project } from '../../../../../shared/models';
44
export interface ProjectState {
55
projects: Project[];
66
customerProjects: Project[];
7+
recentProjects: Project[];
78
isLoading: boolean;
89
message: string;
910
projectToEdit: Project;
@@ -12,6 +13,7 @@ export interface ProjectState {
1213
export const initialState = {
1314
projects: [],
1415
customerProjects: [],
16+
recentProjects: [],
1517
isLoading: false,
1618
message: '',
1719
projectToEdit: undefined,
@@ -65,6 +67,21 @@ export const projectReducer = (state: ProjectState = initialState, action: Proje
6567
};
6668
}
6769

70+
case ProjectActionTypes.LOAD_RECENT_PROJECTS_SUCCESS:
71+
return {
72+
...state,
73+
recentProjects: action.payload,
74+
isLoading: false
75+
};
76+
77+
case ProjectActionTypes.LOAD_RECENT_PROJECTS_FAIL: {
78+
return {
79+
...state,
80+
recentProjects: [],
81+
isLoading: false,
82+
};
83+
}
84+
6885
case ProjectActionTypes.CREATE_PROJECT: {
6986
return {
7087
...state,

0 commit comments

Comments
 (0)