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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ lib/coverage/
yarn.lock
.vscode/
npm-debug.log
lib/package-lock\.json
package-lock\.json
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ customerFormValidation
console.log(validationResult.success); // true
console.log(validationResult.formGlobalErrors); // []
console.log(validationResult.fieldErrors);
/*[
{ succeeded: true, type: "REQUIRED", key: "firstName", errorMessage: "" },
{ succeeded: true, type: "REQUIRED", key: "lastName", errorMessage: "" }
]*/
/*{
firstName: { succeeded: true, type: "REQUIRED", key: "firstName", errorMessage: "" },
lastName: { succeeded: true, type: "REQUIRED", key: "lastName", errorMessage: "" }
}*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't remember what was the intention when we create the readme about this commented code, dou you know why?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see it's dumping the result, it's from a previous version (even previous that current)

})
.catch((error) => {
// handle unexpected errors
Expand Down Expand Up @@ -240,7 +240,7 @@ testFormValidation
.then((validationResult) => {
console.log(validationResult.succeeded); // true
console.log(validationResult.formGlobalErrors) // []
console.log(validationResult.fieldErrors); // []
console.log(validationResult.fieldErrors); // {}
})
.catch((error) => {
// handle unexpected errors
Expand Down
2 changes: 1 addition & 1 deletion lib/lc-form-validation.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export class FieldValidationResult {

export class FormValidationResult {
succeeded: boolean;
fieldErrors: Array<FieldValidationResult>;
fieldErrors: { [key: string]: FieldValidationResult };
formGlobalErrors: Array<FieldValidationResult>;
}

Expand Down
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.3",
"version": "2.0.0",
"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 @@ -84,6 +84,7 @@
],
"dependencies": {
"es6-promise": "4.1.0",
"lodash.get": "^4.4.2"
"lodash.get": "^4.4.2",
"lodash.set": "^4.3.2"
}
}
4 changes: 2 additions & 2 deletions lib/src/entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ export class FieldValidationResult {

export class FormValidationResult {
succeeded: boolean;
fieldErrors: FieldValidationResult[];
fieldErrors: { [key: string]: FieldValidationResult };
formGlobalErrors: FieldValidationResult[];

constructor() {
this.succeeded = false;
this.fieldErrors = [];
this.fieldErrors = {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MMM... I think this is a breaking change, should we go for a major release?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think it should be major

}
}

Expand Down
284 changes: 168 additions & 116 deletions lib/src/spec/validationEngineValidateForm.spec.ts

Large diffs are not rendered by default.

99 changes: 75 additions & 24 deletions lib/src/spec/validationsResultBuilder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ describe('ValidationsResultBuilder ', () => {
expect(result.succeeded).to.be.true;
});

it('Spec #8 => should returns new FormValidationResult equals { fieldErrors: [] } ' +
it('Spec #8 => should returns new FormValidationResult equals { fieldErrors: {} } ' +
'when passing fieldValidationResults equals undefined', () => {
//Arrange
let fieldValidationResults = undefined;
Expand All @@ -113,10 +113,10 @@ describe('ValidationsResultBuilder ', () => {
let result = validationsResultBuilder.buildFormValidationsResult(fieldValidationResults);

//Assert
expect(result.fieldErrors).to.be.empty;
expect(result.fieldErrors).to.deep.equals({});
});

it('Spec #9 => should returns new FormValidationResult equals { fieldErrors: [] } ' +
it('Spec #9 => should returns new FormValidationResult equals { fieldErrors: {} } ' +
'when passing fieldValidationResults equals null', () => {
//Arrange
let fieldValidationResults = null;
Expand All @@ -125,10 +125,10 @@ describe('ValidationsResultBuilder ', () => {
let result = validationsResultBuilder.buildFormValidationsResult(fieldValidationResults);

//Assert
expect(result.fieldErrors).to.be.empty;
expect(result.fieldErrors).to.deep.equals({});
});

it('Spec #10 => should returns new FormValidationResult equals { fieldErrors: [] } ' +
it('Spec #10 => should returns new FormValidationResult equals { fieldErrors: {} } ' +
'when passing fieldValidationResults equals empty', () => {
//Arrange
let fieldValidationResults = [];
Expand All @@ -137,11 +137,11 @@ describe('ValidationsResultBuilder ', () => {
let result = validationsResultBuilder.buildFormValidationsResult(fieldValidationResults);

//Assert
expect(result.fieldErrors).to.be.empty;
expect(result.fieldErrors).to.deep.equals({});
});

it('Spec #11 => should returns new FormValidationResult equals ' +
'{ fieldErrors: [{ key: "test" }] } with length equals 1 ' +
'{ fieldErrors: { test: { key: "test", succeeded: false, errorMessage: "", type: "" } } }' +
'when passing fieldValidationResults with one item equals { key: "test" }', () => {
//Arrange
let fieldValidationResult = new FieldValidationResult();
Expand All @@ -152,12 +152,18 @@ describe('ValidationsResultBuilder ', () => {
let result = validationsResultBuilder.buildFormValidationsResult(fieldValidationResults);

//Assert
expect(result.fieldErrors).to.have.length(1);
expect(result.fieldErrors[0].key).to.be.equal('test');
expect(result.fieldErrors).to.deep.equal({
test: {
key: 'test',
succeeded: false,
errorMessage: '',
type: '',
} as FieldValidationResult,
});
});

it('Spec #12 => should returns new FormValidationResult equals ' +
'{ fieldErrors: [] } with length equals 0 ' +
'{ fieldErrors: {} } without properties ' +
'when passing fieldValidationResults with one item equals { key: null }', () => {
//Arrange
let fieldValidationResult = new FieldValidationResult();
Expand All @@ -168,11 +174,11 @@ describe('ValidationsResultBuilder ', () => {
let result = validationsResultBuilder.buildFormValidationsResult(fieldValidationResults);

//Assert
expect(result.fieldErrors).to.have.length(0);
expect(result.fieldErrors).to.deep.equals({});
});

it('Spec #13 => should returns new FormValidationResult equals ' +
'{ fieldErrors: [] } with length equals 0 ' +
'{ fieldErrors: {} } without properties ' +
'when passing fieldValidationResults with one item equals { key: undefined }', () => {
//Arrange
let fieldValidationResult = new FieldValidationResult();
Expand All @@ -183,11 +189,11 @@ describe('ValidationsResultBuilder ', () => {
let result = validationsResultBuilder.buildFormValidationsResult(fieldValidationResults);

//Assert
expect(result.fieldErrors).to.have.length(0);
expect(result.fieldErrors).to.deep.equals({});
});

it('Spec #14 => should returns new FormValidationResult equals ' +
'{ fieldErrors: [] } with length equals 0 ' +
'{ fieldErrors: {} } without properties ' +
'when passing fieldValidationResults with one item equals { key: "" }', () => {
//Arrange
let fieldValidationResult = new FieldValidationResult();
Expand All @@ -198,11 +204,11 @@ describe('ValidationsResultBuilder ', () => {
let result = validationsResultBuilder.buildFormValidationsResult(fieldValidationResults);

//Assert
expect(result.fieldErrors).to.have.length(0);
expect(result.fieldErrors).to.deep.equals({});
});

it('Spec #15 => should returns new FormValidationResult equals ' +
'{ fieldErrors: [] } with length equals 0 ' +
'{ fieldErrors: {} } without properties ' +
'when passing fieldValidationResults with one item equals { key: "_GLOBAL_FORM_" }', () => {
//Arrange
let fieldValidationResult = new FieldValidationResult();
Expand All @@ -213,7 +219,7 @@ describe('ValidationsResultBuilder ', () => {
let result = validationsResultBuilder.buildFormValidationsResult(fieldValidationResults);

//Assert
expect(result.fieldErrors).to.have.length(0);
expect(result.fieldErrors).to.deep.equals({});
});

it('Spec #16 => should returns new FormValidationResult equals ' +
Expand Down Expand Up @@ -296,7 +302,7 @@ describe('ValidationsResultBuilder ', () => {
});

it('Spec #21 => should returns new FormValidationResult equals ' +
'{ fieldErrors: [{ key: "test" }] } with length equals 1 ' +
'{ fieldErrors: { test: { key: "test" } } } ' +
'when passing fieldValidationResults with two item first equals { key: "test" }' +
'and second equals null', () => {
//Arrange
Expand All @@ -311,12 +317,18 @@ describe('ValidationsResultBuilder ', () => {
let result = validationsResultBuilder.buildFormValidationsResult(fieldValidationResults);

//Assert
expect(result.fieldErrors).to.have.length(1);
expect(result.fieldErrors[0].key).to.be.equal('test');
expect(result.fieldErrors).to.deep.equal({
test: {
key: 'test',
succeeded: false,
errorMessage: '',
type: '',
} as FieldValidationResult,
});
});

it('Spec #22 => should returns new FormValidationResult equals ' +
'{ fieldErrors: [{ key: "test" }] } with length equals 1 ' +
'{ fieldErrors: { test: { key: "test" } } } ' +
'when passing fieldValidationResults with two item first equals { key: "test" }' +
'and second equals undefined', () => {
//Arrange
Expand All @@ -331,11 +343,50 @@ describe('ValidationsResultBuilder ', () => {
let result = validationsResultBuilder.buildFormValidationsResult(fieldValidationResults);

//Assert
expect(result.fieldErrors).to.have.length(1);
expect(result.fieldErrors[0].key).to.be.equal('test');
expect(result.fieldErrors).to.deep.equal({
test: {
key: 'test',
succeeded: false,
errorMessage: '',
type: '',
} as FieldValidationResult,
});
});

it('Spec #23 => should returns new FormValidationResult equals ' +
'{ fieldErrors: { test1: { key: "test1" }, test2: { key: "test2" } } } ' +
'when passing fieldValidationResults with two item first equals { key: "test1" }' +
'and second equals { key: "test2" }', () => {
//Arrange
const fieldValidationResult1 = new FieldValidationResult();
fieldValidationResult1.key = 'test1';

const fieldValidationResult2 = new FieldValidationResult();
fieldValidationResult2.key = 'test2';

const fieldValidationResults = [fieldValidationResult1, fieldValidationResult2];

//Act
const result = validationsResultBuilder.buildFormValidationsResult(fieldValidationResults);

//Assert
expect(result.fieldErrors).to.deep.equal({
test1: {
key: 'test1',
succeeded: false,
errorMessage: '',
type: '',
} as FieldValidationResult,
test2: {
key: 'test2',
succeeded: false,
errorMessage: '',
type: '',
} as FieldValidationResult,
});
});

it('Spec #24 => should returns new FormValidationResult equals ' +
'{ formGlobalErrors: [{ key: "_GLOBAL_FORM_" }] } with length equals 1 ' +
'when passing fieldValidationResults with two item first equals { key: "_GLOBAL_FORM_" }' +
'and second equals null', () => {
Expand All @@ -355,7 +406,7 @@ describe('ValidationsResultBuilder ', () => {
expect(result.formGlobalErrors[0].key).to.be.equal('_GLOBAL_FORM_');
});

it('Spec #24 => should returns new FormValidationResult equals ' +
it('Spec #25 => should returns new FormValidationResult equals ' +
'{ formGlobalErrors: [{ key: "_GLOBAL_FORM_" }] } with length equals 1 ' +
'when passing fieldValidationResults with two item first equals { key: "_GLOBAL_FORM_" }' +
'and second equals undefined', () => {
Expand Down
8 changes: 7 additions & 1 deletion lib/src/validationsResultBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { FieldValidationResult, FormValidationResult } from './entities';
import { consts } from './consts';
import set from 'lodash.set';

export class ValidationsResultBuilder {
buildFormValidationsResult(fieldValidationResults: Array<FieldValidationResult>): FormValidationResult {
Expand All @@ -10,7 +11,8 @@ export class ValidationsResultBuilder {
this.setGlobalKeyToEmptyKeys(filteredFieldValidationResults);

formValidationResult.succeeded = filteredFieldValidationResults.every(fvr => fvr.succeeded);
formValidationResult.fieldErrors = filteredFieldValidationResults.filter(fvr => fvr.key !== consts.globalFormValidationId);
const fieldValidationResultList = filteredFieldValidationResults.filter(fvr => fvr.key !== consts.globalFormValidationId);
formValidationResult.fieldErrors = this.mapFieldValidationResultListToFieldErrorsObject(fieldValidationResultList);
formValidationResult.formGlobalErrors = filteredFieldValidationResults.filter(fvr => fvr.key === consts.globalFormValidationId);
}

Expand All @@ -31,6 +33,10 @@ export class ValidationsResultBuilder {
}
});
}

private mapFieldValidationResultListToFieldErrorsObject = (fieldValidationResultList: FieldValidationResult[]): { [key: string]: FieldValidationResult } => (
fieldValidationResultList.reduce((errors, result) => set(errors, result.key, result), {})
)
}

let validationsResultBuilder = new ValidationsResultBuilder();
Expand Down
5 changes: 3 additions & 2 deletions samples/jquery/00 ShoppingForm/src/modules/app/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import $ from 'jquery';
import { productsService } from '../../services/productsService';
import { productsFormValidation } from './validation/formProductValidationService';

let storedProducts = [];
let $selBrands, $selProducts, $formProducts, $txtNif, $txtDiscount;

class App {
Expand Down Expand Up @@ -94,7 +93,9 @@ class App {
productsFormValidation
.validateForm(vm)
.then(validationResult => {
validationResult.fieldErrors.forEach(this.handleFieldValidationResult($form));
Object.keys(validationResult.fieldErrors).forEach((key) => {
this.handleFieldValidationResult($form)(validationResult.fieldErrors[key]);
});
if (validationResult.succeeded) {
console.log('Form is sent');
}
Expand Down
11 changes: 4 additions & 7 deletions samples/react/es6/00 SimpleForm/src/reducers/customer.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,11 @@ function customerProcessUIInputCompleted(state, action) {
}

function customerSaveCompleted(state, action) {
const newCustomerErrors = { ...state.customerErrors };

action.formValidationResult.fieldErrors.forEach(fieldValidationResult => {
newCustomerErrors[fieldValidationResult.key] = fieldValidationResult;
});

return {
...state,
customerErrors: newCustomerErrors
customerErrors: {
...state.customerErrors,
...action.formValidationResult.fieldErrors,
},
};
}
11 changes: 4 additions & 7 deletions samples/react/es6/01 SignupForm/src/reducers/signup.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,11 @@ function signupProcessCompleted(state, action) {
}

function performSignupCompleted(state, action) {
const newSignupErrors = { ...state.signupErrors };

action.formValidationResult.fieldErrors.forEach(fieldValidationResult => {
newSignupErrors[fieldValidationResult.key] = fieldValidationResult;
});

return {
...state,
signupErrors: newSignupErrors
signupErrors: {
...state.signupErrors,
...action.formValidationResult.fieldErrors,
},
};
}
11 changes: 4 additions & 7 deletions samples/react/typescript/00 SimpleForm/src/reducers/customer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,11 @@ function customerProcessUIInputCompleted(state: CustomerState, action: ICustomer
}

function customerSaveCompleted(state: CustomerState, action: ICustomerSaveCompletedAction): CustomerState {
const newCustomerErrors: CustomerErrors = Object.assign({}, state.customerErrors);

action.formValidationResult.fieldErrors.forEach(fieldValidationResult => {
newCustomerErrors[fieldValidationResult.key] = fieldValidationResult;
});

return {
...state,
customerErrors: newCustomerErrors
customerErrors: {
...state.customerErrors,
...action.formValidationResult.fieldErrors,
}
};
}
3 changes: 2 additions & 1 deletion samples/react/typescript/00 SimpleForm/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"preserveConstEnums": true,
"suppressImplicitAnyIndexErrors": true
"suppressImplicitAnyIndexErrors": true,
"skipLibCheck": true
},
"compileOnSave": false,
"exclude": [
Expand Down
Loading