Skip to content

Commit a8ed619

Browse files
authored
Merge pull request #86 from Lemoncode/feature/composefieldsgetor
Feature/composefieldsgetor
2 parents 21c861b + ac81742 commit a8ed619

7 files changed

+198
-18
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ lib/ReadmeResources/
99
lib/coverage/
1010
yarn.lock
1111
.vscode/
12-
npm-debug.log
12+
npm-debug.log
13+
lib/package-lock\.json

lib/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "lc-form-validation",
3-
"version": "1.0.0",
3+
"version": "1.0.3",
44
"description": "lcFormValidation is an async form validation library heavily based on JavaScript (no HTML attributes or annotations). lcFormValidation is third party / framework agnostic so it can be easily integrated with frameworks like React.",
55
"main": "dist/lc-form-validation.js",
66
"scripts": {
@@ -83,6 +83,7 @@
8383
}
8484
],
8585
"dependencies": {
86-
"es6-promise": "4.1.0"
86+
"es6-promise": "4.1.0",
87+
"lodash.get": "^4.4.2"
8788
}
8889
}

lib/src/spec/validationEngineValidateForm.spec.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,82 @@ describe('ValidationEngine Validate Form', () => {
489489
done();
490490
});
491491
});
492+
493+
it('Spec #9 => should pass validation when feeding viewModel with nested properties, fullname.firstName equals "john" and is validation required', (done) => {
494+
// Arrange
495+
const validationEngine: ValidationEngine = new ValidationEngine();
496+
const viewModel = {
497+
fullname: {
498+
firstName: 'john',
499+
},
500+
};
501+
502+
// Act
503+
validationEngine.addFieldValidation('fullname.firstName',
504+
(value, vm): Promise<FieldValidationResult> => {
505+
let isFieldInformed: boolean = (value != null && value.length > 0);
506+
let errorInfo: string = (isFieldInformed) ? "" : "Mandatory field";
507+
508+
const validationResult: FieldValidationResult = new FieldValidationResult();
509+
validationResult.type = "REQUIRED";
510+
validationResult.succeeded = isFieldInformed;
511+
validationResult.errorMessage = errorInfo;
512+
513+
return Promise.resolve(validationResult);
514+
}
515+
);
516+
517+
validationEngine.validateForm(viewModel)
518+
.then((formValidationResult: FormValidationResult) => {
519+
expect(formValidationResult.succeeded).to.be.true;
520+
521+
expect(formValidationResult.fieldErrors).to.have.length(1);
522+
523+
expect(formValidationResult.fieldErrors[0].succeeded).to.be.true;
524+
expect(formValidationResult.fieldErrors[0].key).to.be.equal('fullname.firstName');
525+
expect(formValidationResult.fieldErrors[0].type).to.equal('REQUIRED');
526+
expect(formValidationResult.fieldErrors[0].errorMessage).to.equal('');
527+
done();
528+
});
529+
});
530+
531+
it('Spec #10 => should fail validation when feeding viewModel with nested properties, fullname.firstName equals "" and is validation required', (done) => {
532+
// Arrange
533+
const validationEngine: ValidationEngine = new ValidationEngine();
534+
const viewModel = {
535+
fullname: {
536+
firstName: '',
537+
},
538+
};
539+
540+
// Act
541+
validationEngine.addFieldValidation('fullname.firstName',
542+
(value, vm): Promise<FieldValidationResult> => {
543+
let isFieldInformed: boolean = (value != null && value.length > 0);
544+
let errorInfo: string = (isFieldInformed) ? "" : "Mandatory field";
545+
546+
const validationResult: FieldValidationResult = new FieldValidationResult();
547+
validationResult.type = "REQUIRED";
548+
validationResult.succeeded = isFieldInformed;
549+
validationResult.errorMessage = errorInfo;
550+
551+
return Promise.resolve(validationResult);
552+
}
553+
);
554+
555+
validationEngine.validateForm(viewModel)
556+
.then((formValidationResult: FormValidationResult) => {
557+
expect(formValidationResult.succeeded).to.be.false;
558+
559+
expect(formValidationResult.fieldErrors).to.have.length(1);
560+
561+
expect(formValidationResult.fieldErrors[0].succeeded).to.be.false;
562+
expect(formValidationResult.fieldErrors[0].key).to.be.equal('fullname.firstName');
563+
expect(formValidationResult.fieldErrors[0].type).to.equal('REQUIRED');
564+
expect(formValidationResult.fieldErrors[0].errorMessage).to.equal('Mandatory field');
565+
done();
566+
});
567+
});
492568
});
493569

494570
describe('Group #2 => When calling validateForm and addFormValidation with async function', () => {

lib/src/spec/validationEngineValidateSingleField.spec.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,89 @@ describe('lcFormValidation simple form', () => {
133133
expect(promise).to.eventually.be.rejected.and.notify(done);
134134
});
135135

136+
it('should pass validation when feeding viewModel with nested properties, value equals "john" and validation required',
137+
(done) => {
138+
// Arrange
139+
const formValidationBase: ValidationEngine = new ValidationEngine();
140+
const viewModel = {
141+
id: '1',
142+
fullname: {
143+
firstName: '',
144+
secondName: 'doe',
145+
},
146+
};
147+
148+
const value = 'john';
149+
150+
// Act
151+
formValidationBase.addFieldValidation('fullname.firstName',
152+
(value, vm): Promise<FieldValidationResult> => {
153+
let isFieldInformed: boolean = (value != null && value.length > 0);
154+
155+
let errorInfo: string = (isFieldInformed) ? "" : "Mandatory field";
156+
157+
const validationResult: FieldValidationResult = new FieldValidationResult();
158+
validationResult.type = "REQUIRED";
159+
validationResult.succeeded = isFieldInformed;
160+
validationResult.errorMessage = errorInfo;
161+
162+
return Promise.resolve(validationResult);
163+
}
164+
);
165+
166+
formValidationBase
167+
.validateField(viewModel, 'fullname.firstName', value)
168+
.then((fieldValidationResult: FieldValidationResult) => {
169+
170+
// Assert
171+
expect(fieldValidationResult.key).to.be.equal('fullname.firstName');
172+
expect(fieldValidationResult.type).to.equal('REQUIRED');
173+
expect(fieldValidationResult.succeeded).to.be.true;
174+
expect(fieldValidationResult.errorMessage).to.be.empty;
175+
done();
176+
});
177+
});
178+
179+
it('should fail validation when feeding viewModel with nested properties, value equals "" and validation required',
180+
(done) => {
181+
// Arrange
182+
const formValidationBase: ValidationEngine = new ValidationEngine();
183+
const viewModel = {
184+
id: '1',
185+
fullname: {
186+
firstName: '',
187+
secondName: 'doe',
188+
},
189+
};
190+
191+
const value = '';
192+
193+
// Act
194+
formValidationBase.addFieldValidation('fullname.firstName',
195+
(value, vm): Promise<FieldValidationResult> => {
196+
let isFieldInformed: boolean = (value != null && value.length > 0);
197+
198+
let errorInfo: string = (isFieldInformed) ? "" : "Mandatory field";
199+
200+
const validationResult: FieldValidationResult = new FieldValidationResult();
201+
validationResult.type = "REQUIRED";
202+
validationResult.succeeded = isFieldInformed;
203+
validationResult.errorMessage = errorInfo;
204+
205+
return Promise.resolve(validationResult);
206+
}
207+
);
208+
209+
formValidationBase
210+
.validateField(viewModel, 'fullname.firstName', value)
211+
.then((fieldValidationResult: FieldValidationResult) => {
212+
213+
// Assert
214+
expect(fieldValidationResult.key).to.be.equal('fullname.firstName');
215+
expect(fieldValidationResult.type).to.equal('REQUIRED');
216+
expect(fieldValidationResult.succeeded).to.be.false;
217+
expect(fieldValidationResult.errorMessage).to.equal('Mandatory field');
218+
done();
219+
});
220+
});
136221
});

lib/src/spec/validationsDispatcher.spec.ts

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ describe('ValidationsDispatcher', () => {
399399
});
400400
});
401401

402-
it('Spec #11 => should return empty FieldValidationResult and calls to validation functions ' +
402+
it('Spec #12 => should return empty FieldValidationResult and calls to validation functions ' +
403403
'When passing vm equals undefined, value equals undefined and validationsPerField equals array with one item ' +
404404
'equals validation function resolving a fieldValidationResult equals ""', (done) => {
405405
//Arrange
@@ -433,7 +433,7 @@ describe('ValidationsDispatcher', () => {
433433
});
434434
});
435435

436-
it('Spec #12 => should return undefined FieldValidationResult and calls to first validation function ' +
436+
it('Spec #13 => should return undefined FieldValidationResult and calls to first validation function ' +
437437
'When passing vm equals undefined, value equals undefined and validationsPerField equals array with two items ' +
438438
'first equals validation function resolving a fieldValidationResult equals undefined' +
439439
'second equals successful validation function', (done) => {
@@ -484,7 +484,7 @@ describe('ValidationsDispatcher', () => {
484484
});
485485
});
486486

487-
it('Spec #13 => should return undefined FieldValidationResult and calls to first validation function ' +
487+
it('Spec #14 => should return undefined FieldValidationResult and calls to first validation function ' +
488488
'When passing vm equals undefined, value equals undefined and validationsPerField equals array with two items ' +
489489
'first equals validation function resolving a fieldValidationResult equals undefined' +
490490
'second equals failed validation function', (done) => {
@@ -534,7 +534,7 @@ describe('ValidationsDispatcher', () => {
534534
});
535535
});
536536

537-
it('Spec #14 => should return failed and key equals "test1" FieldValidationResult and calls to first validation function ' +
537+
it('Spec #15 => should return failed and key equals "test1" FieldValidationResult and calls to first validation function ' +
538538
'When passing vm equals undefined, value equals undefined and validationsPerField equals array with two items ' +
539539
'first equals failed validation function' +
540540
'second equals validation function resolving a fieldValidationResult equals undefined', (done) => {
@@ -586,7 +586,7 @@ describe('ValidationsDispatcher', () => {
586586
});
587587
});
588588

589-
it('Spec #15 => should return undefined FieldValidationResult and calls to first and second validation functions ' +
589+
it('Spec #16 => should return undefined FieldValidationResult and calls to first and second validation functions ' +
590590
'When passing vm equals undefined, value equals undefined and validationsPerField equals array with two items ' +
591591
'first equals successful validation function' +
592592
'second equals validation function resolving a fieldValidationResult equals undefined', (done) => {
@@ -636,7 +636,7 @@ describe('ValidationsDispatcher', () => {
636636
});
637637
});
638638

639-
it('should pass customParams to its proper validationFunction', (done) => {
639+
it('Spec #17 => should pass customParams to its proper validationFunction', (done) => {
640640
//Arrange
641641
const vm = undefined;
642642
const value = undefined;
@@ -800,7 +800,7 @@ describe('ValidationsDispatcher', () => {
800800
});
801801

802802
it('Spec #9 => should return empty array and should not call to validationFn ' +
803-
'when passing vm equals { }, vmKeys as non empty array and validationFn equals function', () => {
803+
'when passing vm equals { testVmProperty: "" }, vmKeys equals ["otherProperty"] and validationFn equals function', () => {
804804
//Arrange
805805
const vm = {
806806
testVmProperty: ''
@@ -816,8 +816,8 @@ describe('ValidationsDispatcher', () => {
816816
expect(validationFnSpy.called).to.be.false;
817817
});
818818

819-
it('Spec #10 => should not return empty array with one item and it calls to validationFn ' +
820-
'when passing vm equals { testVmProperty: "test" }, vmKeys equals [] and validationFn equals function', () => {
819+
it('Spec #10 => should return array with one item and it calls to validationFn ' +
820+
'when passing vm equals { testVmProperty: "test" }, vmKeys equals [testVmProperty] and validationFn equals function', () => {
821821
//Arrange
822822
const vm = {
823823
testVmProperty: 'test'
@@ -828,6 +828,25 @@ describe('ValidationsDispatcher', () => {
828828
//Act
829829
const fieldValidationResultPromises = validationsDispatcher.fireAllFieldsValidations(vm, vmKeys, validationFnSpy);
830830

831+
//Ass
832+
expect(fieldValidationResultPromises).to.have.length(1);
833+
expect(validationFnSpy.called).to.be.true;
834+
});
835+
836+
it('Spec #11 => should return array with one item and it calls to validationFn ' +
837+
'when passing vm equals { test: { property: "test"} }, vmKeys equals ["test.property"] and validationFn equals function', () => {
838+
//Arrange
839+
const vm = {
840+
test: {
841+
property: 'test',
842+
},
843+
};
844+
const vmKeys = ['test.property'];
845+
const validationFnSpy = sinon.spy();
846+
847+
//Act
848+
const fieldValidationResultPromises = validationsDispatcher.fireAllFieldsValidations(vm, vmKeys, validationFnSpy);
849+
831850
//Ass
832851
expect(fieldValidationResultPromises).to.have.length(1);
833852
expect(validationFnSpy.called).to.be.true;
@@ -957,7 +976,7 @@ describe('ValidationsDispatcher', () => {
957976
it('Spec #9 => should return array with one item and it calls to validationFn' +
958977
'When passing vm equals function, validations equals array with one validationFn', () => {
959978
//Arrange
960-
const vm = function () {
979+
const vm = function() {
961980
return "this is a function";
962981
};
963982
const validationFnSpy = sinon.spy();

lib/src/validationsDispatcher.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ import {
22
FieldValidationResult,
33
ValidationResult,
44
FormValidationFunction,
5-
FieldValidationFunction,
65
FieldValidation,
76
} from './entities';
8-
import { consts } from './consts';
7+
import get from 'lodash.get';
98

109
class ValidationParams {
1110
constructor(
@@ -75,7 +74,7 @@ export class ValidationDispatcher {
7574

7675
if (this.areParametersDefined(vm, validationFn)) {
7776
fieldsToValidate.forEach((field) => {
78-
const vmFieldValue = vm[field];
77+
const vmFieldValue = get(vm, field, undefined);
7978
if (vmFieldValue !== undefined) {
8079
const fieldValidationResultsPromise = validationFn(vm, field, vmFieldValue);
8180
fieldValidationResultsPromises.push(fieldValidationResultsPromise);

lib/webpack.config.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
var path = require("path");
2-
var webpack = require("webpack");
32
var libraryName = 'lc-form-validation';
43
var CopyWebpackPlugin = require('copy-webpack-plugin');
54

@@ -39,7 +38,7 @@ var config = {
3938
]
4039
},
4140

42-
plugins: [
41+
plugins: [
4342
new CopyWebpackPlugin([
4443
{ from: '../../README.md', to: 'README.md' },
4544
{ from: '../../ReadmeResources', to: 'ReadmeResources' }

0 commit comments

Comments
 (0)