Skip to content

Commit

Permalink
Merge pull request #86 from Lemoncode/feature/composefieldsgetor
Browse files Browse the repository at this point in the history
Feature/composefieldsgetor
  • Loading branch information
brauliodiez authored Aug 27, 2018
2 parents 21c861b + ac81742 commit a8ed619
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 18 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ lib/ReadmeResources/
lib/coverage/
yarn.lock
.vscode/
npm-debug.log
npm-debug.log
lib/package-lock\.json
5 changes: 3 additions & 2 deletions lib/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "lc-form-validation",
"version": "1.0.0",
"version": "1.0.3",
"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.",
"main": "dist/lc-form-validation.js",
"scripts": {
Expand Down Expand Up @@ -83,6 +83,7 @@
}
],
"dependencies": {
"es6-promise": "4.1.0"
"es6-promise": "4.1.0",
"lodash.get": "^4.4.2"
}
}
76 changes: 76 additions & 0 deletions lib/src/spec/validationEngineValidateForm.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,82 @@ describe('ValidationEngine Validate Form', () => {
done();
});
});

it('Spec #9 => should pass validation when feeding viewModel with nested properties, fullname.firstName equals "john" and is validation required', (done) => {
// Arrange
const validationEngine: ValidationEngine = new ValidationEngine();
const viewModel = {
fullname: {
firstName: 'john',
},
};

// Act
validationEngine.addFieldValidation('fullname.firstName',
(value, vm): Promise<FieldValidationResult> => {
let isFieldInformed: boolean = (value != null && value.length > 0);
let errorInfo: string = (isFieldInformed) ? "" : "Mandatory field";

const validationResult: FieldValidationResult = new FieldValidationResult();
validationResult.type = "REQUIRED";
validationResult.succeeded = isFieldInformed;
validationResult.errorMessage = errorInfo;

return Promise.resolve(validationResult);
}
);

validationEngine.validateForm(viewModel)
.then((formValidationResult: FormValidationResult) => {
expect(formValidationResult.succeeded).to.be.true;

expect(formValidationResult.fieldErrors).to.have.length(1);

expect(formValidationResult.fieldErrors[0].succeeded).to.be.true;
expect(formValidationResult.fieldErrors[0].key).to.be.equal('fullname.firstName');
expect(formValidationResult.fieldErrors[0].type).to.equal('REQUIRED');
expect(formValidationResult.fieldErrors[0].errorMessage).to.equal('');
done();
});
});

it('Spec #10 => should fail validation when feeding viewModel with nested properties, fullname.firstName equals "" and is validation required', (done) => {
// Arrange
const validationEngine: ValidationEngine = new ValidationEngine();
const viewModel = {
fullname: {
firstName: '',
},
};

// Act
validationEngine.addFieldValidation('fullname.firstName',
(value, vm): Promise<FieldValidationResult> => {
let isFieldInformed: boolean = (value != null && value.length > 0);
let errorInfo: string = (isFieldInformed) ? "" : "Mandatory field";

const validationResult: FieldValidationResult = new FieldValidationResult();
validationResult.type = "REQUIRED";
validationResult.succeeded = isFieldInformed;
validationResult.errorMessage = errorInfo;

return Promise.resolve(validationResult);
}
);

validationEngine.validateForm(viewModel)
.then((formValidationResult: FormValidationResult) => {
expect(formValidationResult.succeeded).to.be.false;

expect(formValidationResult.fieldErrors).to.have.length(1);

expect(formValidationResult.fieldErrors[0].succeeded).to.be.false;
expect(formValidationResult.fieldErrors[0].key).to.be.equal('fullname.firstName');
expect(formValidationResult.fieldErrors[0].type).to.equal('REQUIRED');
expect(formValidationResult.fieldErrors[0].errorMessage).to.equal('Mandatory field');
done();
});
});
});

describe('Group #2 => When calling validateForm and addFormValidation with async function', () => {
Expand Down
85 changes: 85 additions & 0 deletions lib/src/spec/validationEngineValidateSingleField.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,89 @@ describe('lcFormValidation simple form', () => {
expect(promise).to.eventually.be.rejected.and.notify(done);
});

it('should pass validation when feeding viewModel with nested properties, value equals "john" and validation required',
(done) => {
// Arrange
const formValidationBase: ValidationEngine = new ValidationEngine();
const viewModel = {
id: '1',
fullname: {
firstName: '',
secondName: 'doe',
},
};

const value = 'john';

// Act
formValidationBase.addFieldValidation('fullname.firstName',
(value, vm): Promise<FieldValidationResult> => {
let isFieldInformed: boolean = (value != null && value.length > 0);

let errorInfo: string = (isFieldInformed) ? "" : "Mandatory field";

const validationResult: FieldValidationResult = new FieldValidationResult();
validationResult.type = "REQUIRED";
validationResult.succeeded = isFieldInformed;
validationResult.errorMessage = errorInfo;

return Promise.resolve(validationResult);
}
);

formValidationBase
.validateField(viewModel, 'fullname.firstName', value)
.then((fieldValidationResult: FieldValidationResult) => {

// Assert
expect(fieldValidationResult.key).to.be.equal('fullname.firstName');
expect(fieldValidationResult.type).to.equal('REQUIRED');
expect(fieldValidationResult.succeeded).to.be.true;
expect(fieldValidationResult.errorMessage).to.be.empty;
done();
});
});

it('should fail validation when feeding viewModel with nested properties, value equals "" and validation required',
(done) => {
// Arrange
const formValidationBase: ValidationEngine = new ValidationEngine();
const viewModel = {
id: '1',
fullname: {
firstName: '',
secondName: 'doe',
},
};

const value = '';

// Act
formValidationBase.addFieldValidation('fullname.firstName',
(value, vm): Promise<FieldValidationResult> => {
let isFieldInformed: boolean = (value != null && value.length > 0);

let errorInfo: string = (isFieldInformed) ? "" : "Mandatory field";

const validationResult: FieldValidationResult = new FieldValidationResult();
validationResult.type = "REQUIRED";
validationResult.succeeded = isFieldInformed;
validationResult.errorMessage = errorInfo;

return Promise.resolve(validationResult);
}
);

formValidationBase
.validateField(viewModel, 'fullname.firstName', value)
.then((fieldValidationResult: FieldValidationResult) => {

// Assert
expect(fieldValidationResult.key).to.be.equal('fullname.firstName');
expect(fieldValidationResult.type).to.equal('REQUIRED');
expect(fieldValidationResult.succeeded).to.be.false;
expect(fieldValidationResult.errorMessage).to.equal('Mandatory field');
done();
});
});
});
39 changes: 29 additions & 10 deletions lib/src/spec/validationsDispatcher.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ describe('ValidationsDispatcher', () => {
});
});

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

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

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

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

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

it('should pass customParams to its proper validationFunction', (done) => {
it('Spec #17 => should pass customParams to its proper validationFunction', (done) => {
//Arrange
const vm = undefined;
const value = undefined;
Expand Down Expand Up @@ -800,7 +800,7 @@ describe('ValidationsDispatcher', () => {
});

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

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

//Ass
expect(fieldValidationResultPromises).to.have.length(1);
expect(validationFnSpy.called).to.be.true;
});

it('Spec #11 => should return array with one item and it calls to validationFn ' +
'when passing vm equals { test: { property: "test"} }, vmKeys equals ["test.property"] and validationFn equals function', () => {
//Arrange
const vm = {
test: {
property: 'test',
},
};
const vmKeys = ['test.property'];
const validationFnSpy = sinon.spy();

//Act
const fieldValidationResultPromises = validationsDispatcher.fireAllFieldsValidations(vm, vmKeys, validationFnSpy);

//Ass
expect(fieldValidationResultPromises).to.have.length(1);
expect(validationFnSpy.called).to.be.true;
Expand Down Expand Up @@ -957,7 +976,7 @@ describe('ValidationsDispatcher', () => {
it('Spec #9 => should return array with one item and it calls to validationFn' +
'When passing vm equals function, validations equals array with one validationFn', () => {
//Arrange
const vm = function () {
const vm = function() {
return "this is a function";
};
const validationFnSpy = sinon.spy();
Expand Down
5 changes: 2 additions & 3 deletions lib/src/validationsDispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ import {
FieldValidationResult,
ValidationResult,
FormValidationFunction,
FieldValidationFunction,
FieldValidation,
} from './entities';
import { consts } from './consts';
import get from 'lodash.get';

class ValidationParams {
constructor(
Expand Down Expand Up @@ -75,7 +74,7 @@ export class ValidationDispatcher {

if (this.areParametersDefined(vm, validationFn)) {
fieldsToValidate.forEach((field) => {
const vmFieldValue = vm[field];
const vmFieldValue = get(vm, field, undefined);
if (vmFieldValue !== undefined) {
const fieldValidationResultsPromise = validationFn(vm, field, vmFieldValue);
fieldValidationResultsPromises.push(fieldValidationResultsPromise);
Expand Down
3 changes: 1 addition & 2 deletions lib/webpack.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
var path = require("path");
var webpack = require("webpack");
var libraryName = 'lc-form-validation';
var CopyWebpackPlugin = require('copy-webpack-plugin');

Expand Down Expand Up @@ -39,7 +38,7 @@ var config = {
]
},

plugins: [
plugins: [
new CopyWebpackPlugin([
{ from: '../../README.md', to: 'README.md' },
{ from: '../../ReadmeResources', to: 'ReadmeResources' }
Expand Down

0 comments on commit a8ed619

Please sign in to comment.