Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
fix: #304 avoid creating entries with a date after the one that is ru…
…nning
  • Loading branch information
enriquezrene committed May 28, 2020
commit c2bfcfdd737bee23d2de7a41be45575da7e57db3
46 changes: 40 additions & 6 deletions src/app/modules/time-entries/pages/time-entries.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ToastrService } from 'ngx-toastr';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { provideMockStore, MockStore } from '@ngrx/store/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
Expand All @@ -23,6 +24,11 @@ describe('TimeEntriesComponent', () => {
let mockTechnologySelector;
let mockProjectsSelector;
let mockEntriesSelector;
let injectedToastrService;

const toastrService = {
error: () => {},
};

const state = {
projects: {
Expand All @@ -43,6 +49,10 @@ describe('TimeEntriesComponent', () => {
},
entries: {
entryList: [],
active: {
start_date: new Date('2019-01-01T15:36:15.887Z'),
id: 'active-entry',
}
},
};

Expand All @@ -68,13 +78,16 @@ describe('TimeEntriesComponent', () => {
TechnologiesComponent,
TimeEntriesSummaryComponent,
],
providers: [provideMockStore({ initialState: state })],
providers: [provideMockStore({ initialState: state }),
{ provide: ToastrService, useValue: toastrService },
],
imports: [FormsModule, ReactiveFormsModule],
}).compileComponents();
store = TestBed.inject(MockStore);
mockTechnologySelector = store.overrideSelector(allTechnologies, state.technologies);
mockProjectsSelector = store.overrideSelector(getProjects, state.projects.projects);
mockEntriesSelector = store.overrideSelector(allEntries, state.entries.entryList);
injectedToastrService = TestBed.inject(ToastrService);
}));

beforeEach(() => {
Expand Down Expand Up @@ -159,30 +172,51 @@ describe('TimeEntriesComponent', () => {
expect(component.entryId).toBe('entry_1');
});

it('should update entry by id', () => {
it('displays an error when start date of entry is > than active entry start date', () => {
const newEntry = {
project_id: 'projectId',
start_date: '',
project_id: 'p-id',
start_date: '2020-05-05T10:04',
description: 'description',
technologies: [],
uri: 'abc',
};
component.entryId = 'new-entry';
spyOn(injectedToastrService, 'error');

component.saveEntry(newEntry);

expect(injectedToastrService.error).toHaveBeenCalled();
});

it('should dispatch an action when entry is going to be saved', () => {
const newEntry = {
project_id: 'p-id',
start_date: '2020-05-05T10:04',
description: 'description',
technologies: [],
uri: 'abc',
};
component.entryId = 'entry_1';
component.entryId = 'active-entry';
spyOn(store, 'dispatch');

component.saveEntry(newEntry);

expect(store.dispatch).toHaveBeenCalled();
});

it('should create new Entry', () => {
const newEntry = {
project_id: 'projectId',
start_date: '',
start_date: '2010-05-05T10:04',
description: 'description',
technologies: [],
uri: 'abc',
};
component.entryId = undefined;
spyOn(store, 'dispatch');

component.saveEntry(newEntry);

expect(store.dispatch).toHaveBeenCalledWith(new entryActions.CreateEntry(newEntry));
});

Expand Down
26 changes: 20 additions & 6 deletions src/app/modules/time-entries/pages/time-entries.component.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ToastrService } from 'ngx-toastr';
import { getActiveTimeEntry } from './../../time-clock/store/entry.selectors';
import { Component, OnInit } from '@angular/core';
import { Entry } from '../../shared/models';
import { EntryState } from '../../time-clock/store/entry.reducer';
Expand All @@ -14,15 +16,20 @@ export class TimeEntriesComponent implements OnInit {
entryId: string;
entry: Entry;
dataByMonth = [];
activeTimeEntry: Entry;

constructor(private store: Store<EntryState>) {}
constructor(private store: Store<EntryState>, private toastrService: ToastrService) { }

ngOnInit(): void {
this.store.dispatch(new entryActions.LoadEntries(new Date().getMonth() + 1));
const dataByMonth$ = this.store.pipe(select(allEntries));
dataByMonth$.subscribe((response) => {
this.dataByMonth = response;
});
this.store.dispatch(new entryActions.LoadActiveEntry());
this.store.pipe(select(getActiveTimeEntry)).subscribe((activeTimeEntry) => {
this.activeTimeEntry = activeTimeEntry;
});
}

newEntry() {
Expand All @@ -31,17 +38,24 @@ export class TimeEntriesComponent implements OnInit {
}

editEntry(entryId: string) {
console.log(this.dataByMonth);
this.entryId = entryId;
this.entry = this.dataByMonth.find((entry) => entry.id === entryId);
}

saveEntry(entry): void {
if (this.entryId) {
entry.id = this.entryId;
this.store.dispatch(new entryActions.UpdateActiveEntry(entry));
const entryDateAsIso = new Date(entry.start_date).toISOString();
const entryDateAsLocalDate = new Date(entryDateAsIso);
const activeEntryAsLocaldate = new Date(this.activeTimeEntry.start_date);
const isEditingActiveEntry = this.entryId === this.activeTimeEntry.id;
if (!isEditingActiveEntry && entryDateAsLocalDate > activeEntryAsLocaldate) {
this.toastrService.error('You are on the clock and this entry overlaps it, try with earlier times.');
} else {
this.store.dispatch(new entryActions.CreateEntry(entry));
if (this.entryId) {
entry.id = this.entryId;
this.store.dispatch(new entryActions.UpdateActiveEntry(entry));
} else {
this.store.dispatch(new entryActions.CreateEntry(entry));
}
}
}

Expand Down