Skip to content

Commit cadff0d

Browse files
887 validate required fields for internal apps (#990)
* refactor: TTL-887 validate required fields for internal apps * fix: TTL-887 make if condition more readable * test: TTL-887 tests for saving time entries * refactor: TTL-887 improve tests * refactor: TTL-887 english lessons and safari books can skip description and ticket number * refactor: TTL-887 improve tests * feat: TTL-887 move constants to a shared file * refactor: TTL-887 import constants from a shared file * fix: TTL-887 Activity is required toastr --------- Co-authored-by: Santiago220991 <[email protected]>
1 parent bdeb0bd commit cadff0d

File tree

7 files changed

+225
-95
lines changed

7 files changed

+225
-95
lines changed

src/app/modules/shared/components/details-fields/details-fields.component.spec.ts

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ describe('DetailsFieldsComponent', () => {
4545
projects: {
4646
projects: [{ id: 'id', name: 'name', project_type_id: '', customer: { name: 'Juan', description: 'sadsa' } }],
4747
customerProjects: [{ id: 'id', name: 'name', description: 'description', project_type_id: '123' }],
48-
recentProjects: [{ id: 'id', name: 'name', customer: { name: 'Juan'} }],
48+
recentProjects: [{ id: 'id', name: 'name', customer: { name: 'Juan' } }],
4949
isLoading: false,
5050
message: '',
5151
projectToEdit: undefined,
@@ -104,6 +104,19 @@ describe('DetailsFieldsComponent', () => {
104104

105105
const mockCurrentDate = '2020-12-01T12:00:00';
106106

107+
const entryWithoutRequiredFields = {
108+
project_id: 'p1',
109+
project_name: 'ioet inc.',
110+
activity_id: 'a1',
111+
uri: '',
112+
start_date: '2020-02-05',
113+
end_date: '2020-02-05',
114+
start_hour: '00:00',
115+
end_hour: '00:01',
116+
description: '',
117+
technology: '',
118+
};
119+
107120
beforeEach(
108121
waitForAsync(() => {
109122
TestBed.configureTestingModule({
@@ -156,15 +169,15 @@ describe('DetailsFieldsComponent', () => {
156169
});
157170

158171
it('onClearedComponent project id and name are set to empty', () => {
159-
const search = {term: ''};
172+
const search = { term: '' };
160173
component.onClearedComponent(search);
161174

162175
expect(component.project_id.value).toBe('');
163176
expect(component.project_name.value).toBe('');
164177
});
165178

166179
it('should change the listProjectsShowed to listProjects if search is not empty on onClearedComponent', () => {
167-
const search = {term: 'Ioet Inc.'};
180+
const search = { term: 'Ioet Inc.' };
168181
const listProjects: Project[] = [{ id: '1', name: 'abc', status: 'active' }];
169182
component.listProjects = listProjects;
170183
component.onClearedComponent(search);
@@ -708,14 +721,65 @@ describe('DetailsFieldsComponent', () => {
708721
expect(toastrServiceStub.warning).toHaveBeenCalled();
709722
});
710723

711-
it('if entry is set to project_name search_fiend is assigned in entryForm', () => {
712-
const listProjects: Project[] = [{ id: 'id', name: 'abc', status: 'active', search_field: 'name'}];
724+
it('if entry is set to project_name search_field is assigned in entryForm', () => {
725+
const listProjects: Project[] = [{ id: 'id', name: 'abc', status: 'active', search_field: 'name' }];
713726
component.listProjects = listProjects;
714727
component.entryToEdit = { ...entryToEdit };
715728
component.ngOnChanges();
716729
expect(component.entryForm.value.project_name).toBe('name');
717730
});
718731

732+
it('should display a warning message when trying to save time entry of internal app without required fields', () => {
733+
component.entryForm.setValue(entryWithoutRequiredFields);
734+
spyOn(toastrServiceStub, 'warning');
735+
736+
component.onSubmit();
737+
expect(toastrServiceStub.warning).toHaveBeenCalled();
738+
});
739+
740+
it('should not display a warning message when trying to save time entry of internal app with uri and save', () => {
741+
component.entryForm.setValue({ ...entryWithoutRequiredFields, uri: 'TTL-886' });
742+
spyOn(toastrServiceStub, 'warning');
743+
spyOn(component.saveEntry, 'emit');
744+
745+
component.onSubmit();
746+
expect(toastrServiceStub.warning).not.toHaveBeenCalled();
747+
expect(component.saveEntry.emit).toHaveBeenCalled();
748+
});
749+
750+
it('should not display a warning message when trying to save time entry of external customer without required fields and save', () => {
751+
component.entryForm.setValue({ ...entryWithoutRequiredFields, project_name: 'Warby Parker' });
752+
spyOn(component.saveEntry, 'emit');
753+
spyOn(toastrServiceStub, 'warning');
754+
755+
component.onSubmit();
756+
expect(toastrServiceStub.warning).not.toHaveBeenCalled();
757+
758+
expect(component.saveEntry.emit).toHaveBeenCalled();
759+
});
760+
761+
it('should not display a warning message when trying to save time entry of internal app with description and save', () => {
762+
component.entryForm.setValue({ ...entryWithoutRequiredFields, description: 'Description' });
763+
spyOn(component.saveEntry, 'emit');
764+
spyOn(toastrServiceStub, 'warning');
765+
766+
component.onSubmit();
767+
expect(toastrServiceStub.warning).not.toHaveBeenCalled();
768+
expect(component.saveEntry.emit).toHaveBeenCalled();
769+
});
770+
771+
/* We allow saving time entries with empty fields in uri and description for safari books and english lessons */
772+
it('should not display a warning message when trying to save time entry of English Lessons without description and save', () => {
773+
component.entryForm.setValue({ ...entryWithoutRequiredFields, project_name: 'ioet inc. - English Lessons' });
774+
spyOn(toastrServiceStub, 'warning');
775+
spyOn(component.saveEntry, 'emit');
776+
777+
component.onSubmit();
778+
expect(toastrServiceStub.warning).not.toHaveBeenCalled();
779+
780+
expect(component.saveEntry.emit).toHaveBeenCalled();
781+
});
782+
719783
/*
720784
TODO As part of https://github.com/ioet/time-tracker-ui/issues/424 a new parameter was added to the details-field-component,
721785
and now these couple of tests are failing. A solution to this error might be generate a Test Wrapper Component. More details here:

src/app/modules/shared/components/details-fields/details-fields.component.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import { DATE_FORMAT, DATE_FORMAT_YEAR } from 'src/environments/environment';
2727
import { TechnologiesComponent } from '../technologies/technologies.component';
2828
import { MatDatepicker } from '@angular/material/datepicker';
2929
import { Observable } from 'rxjs';
30+
import { EMPTY_FIELDS_ERROR_MESSAGE } from '../../messages';
31+
import { INTERNAL_APP_STRING, PROJECT_NAME_TO_SKIP } from 'src/app/modules/shared/internal-app-constants';
3032

3133
type Merged = TechnologyState & ProjectState & ActivityState & EntryState;
3234
@Component({
@@ -118,8 +120,8 @@ export class DetailsFieldsComponent implements OnChanges, OnInit {
118120
});
119121
}
120122

121-
onClearedComponent({term}) {
122-
const isSearchEmpty = (term === '');
123+
onClearedComponent({ term }) {
124+
const isSearchEmpty = term === '';
123125
if (isSearchEmpty) {
124126
this.isTechnologiesDisabled = true;
125127
this.entryForm.patchValue({
@@ -168,7 +170,7 @@ export class DetailsFieldsComponent implements OnChanges, OnInit {
168170
projectWithSearchField.search_field = `${project.customer.name} - ${project.name}`;
169171
this.listRecentProjects.push(projectWithSearchField);
170172
});
171-
}else{
173+
} else {
172174
this.listRecentProjects = this.listProjects;
173175
}
174176
this.listProjectsShowed = this.listRecentProjects;
@@ -331,6 +333,15 @@ export class DetailsFieldsComponent implements OnChanges, OnInit {
331333
}
332334

333335
onSubmit() {
336+
const emptyValue = '';
337+
const { project_name, uri, description } = this.entryForm.value;
338+
const areEmptyValues = [uri, description].every(item => item === emptyValue);
339+
const canSkipDescriptionAndURI = PROJECT_NAME_TO_SKIP.some(projectNameItem => project_name.includes(projectNameItem));
340+
if (project_name.includes(INTERNAL_APP_STRING) && areEmptyValues && !canSkipDescriptionAndURI) {
341+
this.toastrService.warning(EMPTY_FIELDS_ERROR_MESSAGE);
342+
return;
343+
}
344+
334345
if (this.entryForm.invalid) {
335346
this.toastrService.warning('Make sure to select a project and activity');
336347
return;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export const INTERNAL_APP_STRING = 'ioet';
2+
export const PROJECT_NAME_TO_SKIP = ['English Lessons', 'Safari Books'];

src/app/modules/shared/messages.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export const INFO_SAVED_SUCCESSFULLY = 'The data has been saved successfully';
22
export const INFO_DELETE_SUCCESSFULLY = 'The data has been deleted successfully';
33
export const UNEXPECTED_ERROR = 'An unexpected error happened, please try again later';
44
export const PROJECT_DEACTIVATED_SUCCESSFULLY = 'The project has been inactivated successfully';
5+
export const EMPTY_FIELDS_ERROR_MESSAGE = 'Make sure to add a description and/or ticket number when working on an internal app.';

0 commit comments

Comments
 (0)