diff --git a/src/app/modules/shared/components/details-fields/details-fields.component.html b/src/app/modules/shared/components/details-fields/details-fields.component.html index 728c93d83..14da7fb7f 100644 --- a/src/app/modules/shared/components/details-fields/details-fields.component.html +++ b/src/app/modules/shared/components/details-fields/details-fields.component.html @@ -1,135 +1,143 @@ -
-
+
+
Project
-
- - - - - - -
-
-
+
- -
-
- Activity -
- +
+
+ Activity
+ +
-
-
- Ticket -
- +
+
+ Ticket
+ +
-
-
- Start/Date -
- -
- Start/Hour -
- +
+
+ Start/Date
-
-
- End/Date -
- -
- End/Hour -
- + +
+ Start/Hour
-
-
- Technology -
- + +
+
+
+ End/Date
- -
LOADING...
-
-
- {{ item.name }} -
+ +
+ End/Hour
-
-
- {{ technology }} - -
+ +
+
+
+ Technology
+ +
-
- - +
LOADING...
+
+
+ {{ item.name }}
- +
+
+ {{ technology }} +
- -
+
+ +
+ + +
+ + diff --git a/src/app/modules/shared/components/details-fields/details-fields.component.scss b/src/app/modules/shared/components/details-fields/details-fields.component.scss index 3644986d4..a4b5f6fbb 100644 --- a/src/app/modules/shared/components/details-fields/details-fields.component.scss +++ b/src/app/modules/shared/components/details-fields/details-fields.component.scss @@ -80,6 +80,13 @@ } } +.validation::ng-deep { + .autocomplete .autocomplete-container { + border: 1px solid red; + } +} + + input[type="date"]::-webkit-calendar-picker-indicator { position: absolute; top: 0; @@ -98,5 +105,5 @@ input[type="date"]::-webkit-inner-spin-button { } input[type="date"]::-webkit-clear-button { - z-index: 1; + display: none; } diff --git a/src/app/modules/shared/components/details-fields/details-fields.component.spec.ts b/src/app/modules/shared/components/details-fields/details-fields.component.spec.ts index 04a79a947..c42e6b143 100644 --- a/src/app/modules/shared/components/details-fields/details-fields.component.spec.ts +++ b/src/app/modules/shared/components/details-fields/details-fields.component.spec.ts @@ -9,15 +9,18 @@ import { DetailsFieldsComponent } from './details-fields.component'; import * as actions from '../../store/technology.actions'; import { ProjectState } from '../../../customer-management/components/projects/components/store/project.reducer'; import { getCustomerProjects } from '../../../customer-management/components/projects/components/store/project.selectors'; +import { EntryState } from '../../../time-clock/store/entry.reducer'; +import { getUpdateError, getCreateError } from 'src/app/modules/time-clock/store/entry.selectors'; describe('DetailsFieldsComponent', () => { - type Merged = TechnologyState & ProjectState; + type Merged = TechnologyState & ProjectState & EntryState; let component: DetailsFieldsComponent; let fixture: ComponentFixture; let store: MockStore; let mockTechnologySelector; let mockProjectsSelector; - let length; + let mockEntriesUpdateErrorSelector; + let mockEntriesCreateErrorSelector; const state = { projects: { @@ -37,9 +40,14 @@ describe('DetailsFieldsComponent', () => { message: 'Data fetch successfully!', activityIdToEdit: '', }, + Entries: { + createError: null, + updateError: null, + }, }; const initialData = { + project: '', activity: '', uri: '', start_date: formatDate(new Date(), 'yyyy-MM-dd', 'en'), @@ -47,6 +55,7 @@ describe('DetailsFieldsComponent', () => { start_hour: '00:00', end_hour: '00:00', description: '', + technology: '', }; beforeEach(async(() => { @@ -58,6 +67,8 @@ describe('DetailsFieldsComponent', () => { store = TestBed.inject(MockStore); mockTechnologySelector = store.overrideSelector(allTechnologies, state.technologies); mockProjectsSelector = store.overrideSelector(getCustomerProjects, state.projects); + mockEntriesUpdateErrorSelector = store.overrideSelector(getUpdateError, state.Entries.updateError); + mockEntriesCreateErrorSelector = store.overrideSelector(getCreateError, state.Entries.createError); })); beforeEach(() => { @@ -74,8 +85,6 @@ describe('DetailsFieldsComponent', () => { component.entryToEdit = null; component.ngOnChanges(); expect(component.entryForm.value).toEqual(initialData); - expect(component.projectName).toEqual(''); - expect(component.project).toEqual(''); }); it('should emit ngOnChange with new data', () => { @@ -91,6 +100,7 @@ describe('DetailsFieldsComponent', () => { description: '', }; const formValue = { + project: 'name', activity: 'abc', uri: 'ticketUri', start_date: '2020-02-05', @@ -98,12 +108,11 @@ describe('DetailsFieldsComponent', () => { start_hour: '14:36', end_hour: '15:36', description: '', + technology: '', }; - component.project = project; component.entryToEdit = entryToEdit; component.ngOnChanges(); expect(component.entryForm.value).toEqual(formValue); - expect(component.projectName).toEqual(project.name); }); it('should emit ngOnChange with new data', () => { @@ -117,6 +126,7 @@ describe('DetailsFieldsComponent', () => { description: '', }; const formValue = { + project: 'name', activity: '', uri: 'ticketUri', start_date: '', @@ -124,16 +134,16 @@ describe('DetailsFieldsComponent', () => { start_hour: '00:00', end_hour: '00:00', description: '', + technology: '', }; - component.project = project; component.entryToEdit = entryToEdit; component.ngOnChanges(); expect(component.entryForm.value).toEqual(formValue); - expect(component.projectName).toEqual(project.name); }); it('should emit ngOnChange with new data', () => { const formValue = { + project: '', activity: '', uri: '', start_date: formatDate(new Date(), 'yyyy-MM-dd', 'en'), @@ -141,11 +151,11 @@ describe('DetailsFieldsComponent', () => { start_hour: '00:00', end_hour: '00:00', description: '', + technology: '' }; component.entryToEdit = null; component.ngOnChanges(); expect(component.entryForm.value).toEqual(formValue); - expect(component.projectName).toEqual(''); }); it('should dispatch FindTechnology action #getTechnologies', () => { @@ -216,7 +226,7 @@ describe('DetailsFieldsComponent', () => { spyOn(component.saveEntry, 'emit'); component.onSubmit(); const data = { - project_id: undefined, + project_id: null, activity_id: null, technologies: [], description: '', @@ -230,6 +240,7 @@ describe('DetailsFieldsComponent', () => { it('should emit saveEntry without project and activite fields event', () => { spyOn(component.saveEntry, 'emit'); component.entryForm.setValue({ + project: 'name', activity: 'activity1', uri: '', start_date: '', @@ -237,14 +248,14 @@ describe('DetailsFieldsComponent', () => { start_hour: '00:00', end_hour: '00:00', description: '', + technology: '', }); - component.projectName = { id: 'abc', name: 'name' }; component.activities = [ { id: 'fc5fab41-a21e-4155-9d05-511b956ebd05', tenant_id: 'ioet', name: 'activity1', description: '' }, ]; component.onSubmit(); const data = { - project_id: 'abc', + project_id: 'id', activity_id: 'fc5fab41-a21e-4155-9d05-511b956ebd05', technologies: [], description: '', diff --git a/src/app/modules/shared/components/details-fields/details-fields.component.ts b/src/app/modules/shared/components/details-fields/details-fields.component.ts index e0c850a2c..5c386fe66 100644 --- a/src/app/modules/shared/components/details-fields/details-fields.component.ts +++ b/src/app/modules/shared/components/details-fields/details-fields.component.ts @@ -22,8 +22,11 @@ import { TechnologyState } from '../../store/technology.reducers'; import { LoadActivities, ActivityState, allActivities } from '../../../activities-management/store'; import { getProjects } from '../../../customer-management/components/projects/components/store/project.selectors'; import * as projectActions from '../../../customer-management/components/projects/components/store/project.actions'; +import { EntryState } from '../../../time-clock/store/entry.reducer'; +import * as entryActions from '../../../time-clock/store/entry.actions'; +import { getUpdateError, getCreateError } from 'src/app/modules/time-clock/store/entry.selectors'; -type Merged = TechnologyState & ProjectState & ActivityState; +type Merged = TechnologyState & ProjectState & ActivityState & EntryState; @Component({ selector: 'app-details-fields', @@ -44,8 +47,7 @@ export class DetailsFieldsComponent implements OnChanges, OnInit { activities: Activity[] = []; keyword = 'name'; showlist: boolean; - project: any = {}; - projectName: any = {}; + hoursValidation: boolean; constructor(private formBuilder: FormBuilder, private store: Store, private renderer: Renderer2) { this.renderer.listen('window', 'click', (e: Event) => { @@ -53,8 +55,8 @@ export class DetailsFieldsComponent implements OnChanges, OnInit { this.showlist = false; } }); - this.project = ''; this.entryForm = this.formBuilder.group({ + project: '', activity: '', description: '', start_date: '', @@ -62,6 +64,7 @@ export class DetailsFieldsComponent implements OnChanges, OnInit { start_hour: '00:00', end_hour: '00:00', uri: '', + technology: '', }); } @@ -83,15 +86,31 @@ export class DetailsFieldsComponent implements OnChanges, OnInit { activities$.subscribe((response) => { this.activities = response; }); + + const updateError$ = this.store.pipe(select(getUpdateError)); + updateError$.subscribe((updateError) => { + if (updateError != null && !updateError) { + this.closeEntryModal(); + this.store.dispatch(new entryActions.CleanEntryUpdateError(null)); + } + }); + const createError$ = this.store.pipe(select(getCreateError)); + createError$.subscribe((createError) => { + if (createError != null && !createError) { + this.closeEntryModal(); + this.store.dispatch(new entryActions.CleanEntryCreateError(null)); + } + }); } ngOnChanges(): void { + this.hoursValidation = false; if (this.entryToEdit) { this.selectedTechnology = this.entryToEdit.technologies; - this.project = this.listProjects.find((p) => p.id === this.entryToEdit.project_id); + const project = this.listProjects.find((p) => p.id === this.entryToEdit.project_id); const activity = this.activities.find((a) => a.id === this.entryToEdit.activity_id); - this.projectName = this.project.name; this.entryForm.setValue({ + project: project ? project.name : '', activity: activity ? activity.name : '', description: this.entryToEdit.description, start_date: this.entryToEdit.start_date ? formatDate(this.entryToEdit.start_date, 'yyyy-MM-dd', 'en') : '', @@ -99,12 +118,12 @@ export class DetailsFieldsComponent implements OnChanges, OnInit { end_date: this.entryToEdit.end_date ? formatDate(this.entryToEdit.end_date, 'yyyy-MM-dd', 'en') : '', end_hour: this.entryToEdit.end_date ? formatDate(this.entryToEdit.end_date, 'HH:mm', 'en') : '00:00', uri: this.entryToEdit.uri, + technology: '', }); } else { this.selectedTechnology = []; - this.project = ''; - this.projectName = ''; this.entryForm.setValue({ + project: '', activity: '', description: '', start_date: formatDate(new Date(), 'yyyy-MM-dd', 'en'), @@ -112,6 +131,7 @@ export class DetailsFieldsComponent implements OnChanges, OnInit { end_date: formatDate(new Date(), 'yyyy-MM-dd', 'en'), end_hour: '00:00', uri: '', + technology: '', }); } } @@ -130,17 +150,47 @@ export class DetailsFieldsComponent implements OnChanges, OnInit { } else if (this.selectedTechnology.length < 10) { this.selectedTechnology = [...this.selectedTechnology, name]; } + this.showlist = false; + this.entryForm.get('technology').reset(); } removeTag(index) { this.selectedTechnology.splice(index, 1); } + get project() { + return this.entryForm.get('project'); + } + get activity() { + return this.entryForm.get('activity'); + } + + get start_date() { + return this.entryForm.get('start_date'); + } + + get start_hour() { + return this.entryForm.get('start_hour'); + } + + get end_date() { + return this.entryForm.get('end_date'); + } + + get end_hour() { + return this.entryForm.get('end_hour'); + } + + closeEntryModal() { + this.entryForm.reset(); + this.closeModal.nativeElement.click(); + } + onSubmit() { const activity = this.activities.find((a) => a.name === this.entryForm.value.activity); - this.project = this.projectName.id ? this.projectName : this.project; + const project = this.listProjects.find((p) => p.name === this.entryForm.value.project); const entry = { - project_id: this.project.id, + project_id: project ? project.id : null, activity_id: activity ? activity.id : null, technologies: this.selectedTechnology, description: this.entryForm.value.description, @@ -149,7 +199,5 @@ export class DetailsFieldsComponent implements OnChanges, OnInit { uri: this.entryForm.value.uri, }; this.saveEntry.emit(entry); - this.ngOnChanges(); - this.closeModal.nativeElement.click(); } } diff --git a/src/app/modules/time-clock/pages/time-clock.component.spec.ts b/src/app/modules/time-clock/pages/time-clock.component.spec.ts index 8d33de27f..b4b17dc0d 100644 --- a/src/app/modules/time-clock/pages/time-clock.component.spec.ts +++ b/src/app/modules/time-clock/pages/time-clock.component.spec.ts @@ -1,5 +1,3 @@ - - import { EntryActionTypes, StopTimeEntryRunning } from './../store/entry.actions'; import { async, ComponentFixture, TestBed, inject } from '@angular/core/testing'; import { HttpClientTestingModule } from '@angular/common/http/testing'; @@ -19,7 +17,7 @@ describe('TimeClockComponent', () => { let injectedToastrService; const toastrService = { - success: () => {} + success: () => {}, }; const state = { projects: { @@ -52,7 +50,8 @@ describe('TimeClockComponent', () => { providers: [ AzureAdB2CService, { provide: ToastrService, useValue: toastrService }, - provideMockStore({ initialState: state })], + provideMockStore({ initialState: state }), + ], }).compileComponents(); store = TestBed.inject(MockStore); })); diff --git a/src/app/modules/time-clock/store/entry.actions.ts b/src/app/modules/time-clock/store/entry.actions.ts index d6f745595..3342371bb 100644 --- a/src/app/modules/time-clock/store/entry.actions.ts +++ b/src/app/modules/time-clock/store/entry.actions.ts @@ -21,6 +21,8 @@ export enum EntryActionTypes { STOP_TIME_ENTRY_RUNNING_SUCCESS = '[Entry] STOP_TIME_ENTRIES_RUNNING_SUCCESS', STOP_TIME_ENTRY_RUNNING_FAILED = '[Entry] STOP_TIME_ENTRIES_RUNNING_FAILED', DEFAULT_ENTRY = '[Entry] DEFAULT_ENTRY', + CLEAN_ENTRY_CREATE_ERROR = '[Entry] CLEAN_ENTRY_CREATE_ERROR', + CLEAN_ENTRY_UPDATE_ERROR = '[Entry] CLEAN_ENTRY_UPDATE_ERROR', } export class LoadActiveEntry implements Action { @@ -120,6 +122,16 @@ export class StopTimeEntryRunningFail implements Action { public readonly type = EntryActionTypes.STOP_TIME_ENTRY_RUNNING_FAILED; constructor(public error: string) {} } + +export class CleanEntryCreateError implements Action { + public readonly type = EntryActionTypes.CLEAN_ENTRY_CREATE_ERROR; + constructor(public error: boolean) {} +} + +export class CleanEntryUpdateError implements Action { + public readonly type = EntryActionTypes.CLEAN_ENTRY_UPDATE_ERROR; + constructor(public error: boolean) {} +} export class DefaultEntry implements Action { public readonly type = EntryActionTypes.DEFAULT_ENTRY; } @@ -143,4 +155,6 @@ export type EntryActions = | StopTimeEntryRunning | StopTimeEntryRunningSuccess | StopTimeEntryRunningFail + | CleanEntryCreateError + | CleanEntryUpdateError | DefaultEntry; diff --git a/src/app/modules/time-clock/store/entry.effects.ts b/src/app/modules/time-clock/store/entry.effects.ts index 99e46a683..03be222fd 100644 --- a/src/app/modules/time-clock/store/entry.effects.ts +++ b/src/app/modules/time-clock/store/entry.effects.ts @@ -2,13 +2,14 @@ import { Injectable } from '@angular/core'; import { ofType, Actions, Effect } from '@ngrx/effects'; import { Action } from '@ngrx/store'; import { of, Observable } from 'rxjs'; +import { ToastrService } from 'ngx-toastr'; import { catchError, map, mergeMap } from 'rxjs/operators'; import { EntryService } from '../services/entry.service'; import * as actions from './entry.actions'; @Injectable() export class EntryEffects { - constructor(private actions$: Actions, private entryService: EntryService) {} + constructor(private actions$: Actions, private entryService: EntryService, private toastrService: ToastrService) {} @Effect() loadActiveEntry$: Observable = this.actions$.pipe( @@ -41,9 +42,13 @@ export class EntryEffects { mergeMap((entry) => this.entryService.createEntry(entry).pipe( map((entryData) => { + this.toastrService.success('Entry was saved successfully'); return new actions.CreateEntrySuccess(entryData); }), - catchError((error) => of(new actions.CreateEntryFail(error.error.message))) + catchError((error) => { + this.toastrService.error(error.error.message); + return of(new actions.CreateEntryFail(error.error.message)); + }) ) ) ); @@ -67,9 +72,13 @@ export class EntryEffects { mergeMap((project) => this.entryService.updateActiveEntry(project).pipe( map((projectData) => { + this.toastrService.success('Entry was updated successfully'); return new actions.UpdateActiveEntrySuccess(projectData); }), - catchError((error) => of(new actions.UpdateActiveEntryFail(error))) + catchError((error) => { + this.toastrService.error(error.error.message); + return of(new actions.UpdateActiveEntryFail(error)); + }) ) ) ); diff --git a/src/app/modules/time-clock/store/entry.reducer.spec.ts b/src/app/modules/time-clock/store/entry.reducer.spec.ts index 9cc018f5d..e89f40f4c 100644 --- a/src/app/modules/time-clock/store/entry.reducer.spec.ts +++ b/src/app/modules/time-clock/store/entry.reducer.spec.ts @@ -3,7 +3,14 @@ import * as actions from './entry.actions'; import { entryReducer, EntryState } from './entry.reducer'; describe('entryReducer', () => { - const initialState: EntryState = { active: null, entryList: [], isLoading: false, message: '' }; + const initialState: EntryState = { + active: null, + entryList: [], + isLoading: false, + message: '', + createError: null, + updateError: null, + }; const entry: NewEntry = { start_date: 'start-date', description: 'description', @@ -44,6 +51,7 @@ describe('entryReducer', () => { const action = new actions.LoadActiveEntryFail('error'); const state = entryReducer(initialState, action); expect(state.active).toBe(null); + expect(state.message).toEqual('Something went wrong fetching active entry!'); }); it('on LoadEntries, isLoading is true', () => { @@ -107,8 +115,27 @@ describe('entryReducer', () => { }); it('on DeleteEntrySuccess', () => { - const action = new actions.DeleteEntry('id'); - const state = entryReducer(initialState, action); + const currentState = { + active: null, + entryList: [ + { + project_id: '123', + comments: 'description', + technologies: ['angular', 'javascript'], + uri: 'uri', + id: 'id', + start_date: new Date(), + end_date: new Date(), + activity: 'activity', + }, + ], + isLoading: false, + message: '', + createError: null, + updateError: null, + }; + const action = new actions.DeleteEntrySuccess('id'); + const state = entryReducer(currentState, action); expect(state.entryList).toEqual([]); }); @@ -128,16 +155,50 @@ describe('entryReducer', () => { it('on UpdateActiveEntrySuccess, loading is false', () => { const currentState: EntryState = { active: null, - entryList: [], + entryList: [ + { + project_id: '123', + comments: 'description', + technologies: ['angular', 'javascript'], + uri: 'uri', + id: 'id', + start_date: new Date(), + end_date: new Date(), + activity: 'activity', + }, + ], isLoading: false, message: '', + createError: null, + updateError: null, + }; + const entryUpdated: Entry = { + id: 'id', + start_date: new Date(), + end_date: new Date(), + activity: '', + technologies: ['abc', 'abc'], }; - const action = new actions.UpdateActiveEntrySuccess(newEntry); + const action = new actions.UpdateActiveEntrySuccess(entryUpdated); const state = entryReducer(currentState, action); expect(state.isLoading).toEqual(false); }); + it('on cleanEntryCreateError, createError to be null', () => { + const action = new actions.CleanEntryCreateError(null); + const state = entryReducer(initialState, action); + + expect(state.createError).toBe(null); + }); + + it('on cleanEntryUpdateError, updateError to be null', () => { + const action = new actions.CleanEntryUpdateError(null); + const state = entryReducer(initialState, action); + + expect(state.updateError).toBe(null); + }); + it('on UpdateActiveEntryFail, active to be null', () => { const action = new actions.UpdateActiveEntryFail('error'); const state = entryReducer(initialState, action); diff --git a/src/app/modules/time-clock/store/entry.reducer.ts b/src/app/modules/time-clock/store/entry.reducer.ts index dc6f185da..23e5327c6 100644 --- a/src/app/modules/time-clock/store/entry.reducer.ts +++ b/src/app/modules/time-clock/store/entry.reducer.ts @@ -6,6 +6,8 @@ export interface EntryState { entryList: Entry[]; isLoading: boolean; message: string; + createError: boolean; + updateError: boolean; } export const initialState = { @@ -13,6 +15,8 @@ export const initialState = { entryList: [], isLoading: false, message: '', + createError: null, + updateError: null }; export const entryReducer = (state: EntryState = initialState, action: EntryActions) => { @@ -74,6 +78,7 @@ export const entryReducer = (state: EntryState = initialState, action: EntryActi active: action.payload, entryList: [action.payload, ...state.entryList], isLoading: false, + createError: false, message: 'You clocked-in successfully', }; } @@ -83,6 +88,7 @@ export const entryReducer = (state: EntryState = initialState, action: EntryActi ...state, isLoading: false, message: action.error, + createError: true }; } @@ -127,6 +133,7 @@ export const entryReducer = (state: EntryState = initialState, action: EntryActi ...state, entryList, isLoading: false, + updateError: false, }; } @@ -135,6 +142,7 @@ export const entryReducer = (state: EntryState = initialState, action: EntryActi ...state, active: null, isLoading: false, + updateError: true }; } @@ -162,6 +170,20 @@ export const entryReducer = (state: EntryState = initialState, action: EntryActi }; } + case EntryActionTypes.CLEAN_ENTRY_CREATE_ERROR: { + return { + ...state, + createError: null + }; + } + + case EntryActionTypes.CLEAN_ENTRY_UPDATE_ERROR: { + return { + ...state, + updateError: null + }; + } + default: { return state; } diff --git a/src/app/modules/time-clock/store/entry.selectors.ts b/src/app/modules/time-clock/store/entry.selectors.ts index bbae7cdce..9282e5861 100644 --- a/src/app/modules/time-clock/store/entry.selectors.ts +++ b/src/app/modules/time-clock/store/entry.selectors.ts @@ -8,6 +8,13 @@ export const getActiveTimeEntry = createSelector(getEntryState, (state: EntrySta return state.active; }); +export const getCreateError = createSelector(getEntryState, (state: EntryState) => { + return state.createError; +}); + +export const getUpdateError = createSelector(getEntryState, (state: EntryState) => { + return state.updateError; +}); export const getStatusMessage = createSelector(getEntryState, (state: EntryState) => state.message); export const allEntries = createSelector(getEntryState, (state: EntryState) => state.entryList); diff --git a/src/app/modules/time-entries/pages/time-entries.component.spec.ts b/src/app/modules/time-entries/pages/time-entries.component.spec.ts index d4312a86e..96b6d4ff7 100644 --- a/src/app/modules/time-entries/pages/time-entries.component.spec.ts +++ b/src/app/modules/time-entries/pages/time-entries.component.spec.ts @@ -16,6 +16,7 @@ import { ProjectState } from '../../customer-management/components/projects/comp import { getProjects } from '../../customer-management/components/projects/components/store/project.selectors'; import { EntryState } from '../../time-clock/store/entry.reducer'; import { allEntries } from '../../time-clock/store/entry.selectors'; +import * as entryActions from '../../time-clock/store/entry.actions'; describe('TimeEntriesComponent', () => { type Merged = TechnologyState & ProjectState & EntryState; @@ -151,6 +152,52 @@ describe('TimeEntriesComponent', () => { expect(component.showModal).toBe(true); }); + it('should set entry and entryid to null', () => { + component.newEntry(); + expect(component.entry).toBe(null); + expect(component.entryId).toBe(null); + }); + + it('should set entry and entryid to with data', () => { + component.entryList = [entry]; + component.editEntry('entry_1'); + expect(component.entry).toBe(entry); + expect(component.entryId).toBe('entry_1'); + }); + + it('should update entry by id', () => { + const newEntry = { + project_id: 'projectId', + start_date: '', + description: 'description', + technologies: [], + uri: 'abc', + }; + component.entryId = 'entry_1'; + spyOn(store, 'dispatch'); + component.saveEntry(newEntry); + expect(store.dispatch).toHaveBeenCalled(); + }); + + it('should create new Entry', () => { + const newEntry = { + project_id: 'projectId', + start_date: '', + description: 'description', + technologies: [], + uri: 'abc', + }; + spyOn(store, 'dispatch'); + component.saveEntry(newEntry); + expect(store.dispatch).toHaveBeenCalledWith(new entryActions.CreateEntry(newEntry)); + }); + + it('should delete Entry by id', () => { + spyOn(store, 'dispatch'); + component.removeEntry('id'); + expect(store.dispatch).toHaveBeenCalledWith(new entryActions.DeleteEntry('id')); + }); + it('should get the entry List by Month', () => { const month = 1; component.entryList = [entry];