diff --git a/CHANGELOG.md b/CHANGELOG.md index 68041257f117bd0ac11d1a3ef4dc875d889f7b43..9a0bbab7aba4017943c7bebc19d5068be892d875 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.0.19 - 12-06-2019 +### Added +- A route to POST a form Answer #21 (Horstmann) +- Create ValidationError Class that extends error class, with the objective to return a dictionary of invalid answers (Horstmann) +### Changed +- DbHandler's tests to suite with new forms answers added (Horstmann) +- ValidationHandler to validate a Forms Answer instead of inputsAnswer +- ValidationHandler's tests to suite new method to validate a Forms Answer + + ## 0.0.18 - 25-05-2019 ### Added - Create readFormAnswer method to read formAnswer from database #24 (Horstmann) @@ -12,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Fix OptHandler to return id in inputAnswer + ## 0.0.17 - 25-05-2019 ### Added - inputAnswer method in OptHandler #23 (Horstmann) diff --git a/package.json b/package.json index 5b487a14cfe0d0e283117ed6c52d4512243d296e..3d7f964a200bc1517c0f7413a2e17ac065694635 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "form-creator-api", - "version": "0.0.18", + "version": "0.0.19", "description": "RESTful API used to manage and answer forms.", "main": "index.js", "scripts": { diff --git a/src/api/controllers/formAnswer.spec.ts b/src/api/controllers/formAnswer.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..c88b2f0e621e89745952d51bb65dd9737ff83b56 --- /dev/null +++ b/src/api/controllers/formAnswer.spec.ts @@ -0,0 +1,72 @@ +/* + * form-creator-api. RESTful API to manage and answer forms. + * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre + * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + * + * This file is part of form-creator-api. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + + import * as request from "supertest"; + import { expect } from "chai"; + import * as server from "../../main"; + import { EnumHandler,InputType, ValidationType } from "../../utils/enumHandler"; + import { TestHandler } from "../../utils/testHandler"; + import { OptHandler } from "../../utils/optHandler"; + import { Form, FormOptions } from "../../core/form"; + import { Input, InputOptions, Validation } from "../../core/input"; + + + describe("API data controller", () => { + + it("should respond 200 when posting valid form Answer", (done) => { + + request(server) + .post("/answer/1") + .send({ + 1:["Answer to Question 1 Form 1"] + , 2:["12345-000"] + , 3:["MAXCHAR 10"] + }) + .expect(200) + .expect((res: any) => { + expect(res.body.id).to.be.equal(7); + expect(res.body.message).to.be.equal("Answered"); + }) + .end(done); + }); + + it("should respond 500 when posting invalid form Answer", (done) => { + + request(server) + .post("/answer/1") + .send({ + 1:["Answer to Question 1 Form 1"] + , 2:["12a345-000"] + , 3:["MAXCHAR 10 AND MORE"] + }) + .expect(500) + .expect((res: any) => { + const message = "Could not Create form Answer. Some error has occurred. Check error property for details."; + expect(res.body).to.be.an("object"); + expect(res.body).to.have.property("error"); + expect(res.body.message).to.be.equal(message); + expect(res.body.error["2"]).to.be.equal("RegEx do not match"); + expect(res.body.error["3"]).to.be.equal("Input answer must be lower than 10"); + }) + .end(done); + }); + + }); diff --git a/src/api/controllers/formAnswer.ts b/src/api/controllers/formAnswer.ts new file mode 100644 index 0000000000000000000000000000000000000000..9549a66dd1c643f57f29b9e6e0f636c6b89658e1 --- /dev/null +++ b/src/api/controllers/formAnswer.ts @@ -0,0 +1,102 @@ +/* + * form-creator-api. RESTful API to manage and answer forms. + * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre + * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + * + * This file is part of form-creator-api. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +import { OptHandler } from "../../utils/optHandler"; +import { InputAnswerOptions, InputAnswerOptionsDict } from "../../core/inputAnswer"; +import { Form, FormOptions } from "../../core/form"; +import { FormAnswer, FormAnswerOptions } from "../../core/formAnswer"; +import { ValidationHandler } from "../../utils/validationHandler"; +import { Response, NextFunction } from "express"; +import { Request } from "../apiTypes"; + +export class AnswerCtrl { + + public static write(req: Request, res: Response, next: NextFunction) { + + req.db.readForm(req.params.id, (err: Error, form?: Form) => { + if (err) { + res.status(500).json({ + message: "Form with id: '" + req.params.id + "' not found. Some error has occurred. Check error property for details.", + error: err + }); + return; + } + else { + let inputAnswerOptionsDict: InputAnswerOptionsDict = {} + + for (const key of Object.keys(req.body)) { + inputAnswerOptionsDict[parseInt(key, 10)] = []; + for (const i in req.body[key]) { + const tmpInputAnswerOption: InputAnswerOptions = { + idInput: parseInt(key, 10) + , placement: parseInt(i, 10) + , value: req.body[key][i] + } + inputAnswerOptionsDict[parseInt(key, 10)].push(tmpInputAnswerOption); + } + } + + + let formAnswerOpt: FormAnswerOptions = { + form: form + , timestamp: new Date(Date.now()) + , inputsAnswerOptions: inputAnswerOptionsDict + } + + try{ + const formAnswer: FormAnswer = new FormAnswer(OptHandler.formAnswer(formAnswerOpt)); + ValidationHandler.validateFormAnswer(formAnswer); + req.db.writeFormAnswer(formAnswer, (err: Error, formAnswerResult: FormAnswer) => { + if (err){ + throw err; + } + else{ + res.json({ + id: formAnswerResult.id + , message: "Answered" + }); + return; + } + }); + } + catch (e) { + + if( e.validationDict !== undefined){ + res.status(500).json({ + message: "Could not Create form Answer. Some error has occurred. Check error property for details." + , error: e.validationDict + }); + }else{ + res.status(500).json({ + message: "Could not Create form Answer. Some error has occurred. Check error property for details." + , error: e.message + }); + } + return + } + + } + }); + + } + + +} diff --git a/src/main.ts b/src/main.ts index cbdab0d44b5c5558ca4d5948811aefb8b8022dda..77ed5dc82d942ebb11805d81fd1cdbbebe77a334 100755 --- a/src/main.ts +++ b/src/main.ts @@ -40,6 +40,7 @@ import { DbHandlerMw } from "./api/middlewares/dbHandler"; // Include controllers import { FormCtrl } from "./api/controllers/form"; +import { AnswerCtrl } from "./api/controllers/formAnswer"; // Setup middlewares app.use("/", bodyParser.json()); @@ -50,6 +51,7 @@ app.use("/", DbHandlerMw()); app.get("/forms/", FormCtrl.list); app.get("/forms/:id", FormCtrl.read); app.post("/forms", FormCtrl.write); +app.post("/answer/:id", AnswerCtrl.write); // Listening diff --git a/src/utils/dbHandler.spec.ts b/src/utils/dbHandler.spec.ts index 8f467ab1e85852e7e1e632f3db7b6db90e8071bf..934be6fbc38875c6d20da947f336ecd3605d3c26 100644 --- a/src/utils/dbHandler.spec.ts +++ b/src/utils/dbHandler.spec.ts @@ -267,10 +267,10 @@ describe("Database Handler", () => { }); it("should insert a form answers", (done) => { - const queryString: string = "INSERT INTO form_answer(id, id_form, answered_at)\ + const queryString: string = "INSERT INTO form_answer(id ,id_form, answered_at)\ VALUES\ - (7, 2, '2018-07-02 10:10:25-03'),\ - (8, 3, '2018-06-03 10:11:25-03');"; + (8, 2, '2018-07-02 10:10:25-03'),\ + (9, 3, '2018-06-03 10:11:25-03');"; const query: QueryOptions = {query: queryString, parameters: []}; dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => { @@ -288,7 +288,7 @@ describe("Database Handler", () => { dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => { expect(err).to.be.a("null"); expect(result.command).to.be.equal("SELECT"); - expect(result.rowCount).to.be.equal(8); + expect(result.rowCount).to.be.equal(9); done(); }); }); @@ -306,7 +306,7 @@ describe("Database Handler", () => { }); it("should remove existent form answers", (done) => { - const queryString: string = "DELETE FROM form_answer WHERE id=7 OR id=8;"; + const queryString: string = "DELETE FROM form_answer WHERE id=8 OR id=9;"; const query: QueryOptions = {query: queryString, parameters: []}; dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => { @@ -321,8 +321,8 @@ describe("Database Handler", () => { it("should insert a input answers", (done) => { const queryString: string = "INSERT INTO input_answer(id, id_form_answer, id_input, value, placement)\ VALUES\ - (15,1, 6,'Answer to Question 1 Form 3',1),\ - (16,1, 7,'Answer to Question 2 Form 3',2);"; + (18,1, 6,'Answer to Question 1 Form 3',1),\ + (19,1, 7,'Answer to Question 2 Form 3',2);"; const query: QueryOptions = {query: queryString, parameters: []}; dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => { @@ -340,13 +340,13 @@ describe("Database Handler", () => { dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => { expect(err).to.be.a("null"); expect(result.command).to.be.equal("SELECT"); - expect(result.rowCount).to.be.equal(16); + expect(result.rowCount).to.be.equal(19); done(); }); }); it("should remove non existent input answer", (done) => { - const queryString: string = "DELETE FROM input_answer WHERE id=17;"; + const queryString: string = "DELETE FROM input_answer WHERE id=25;"; const query: QueryOptions = {query: queryString, parameters: []}; dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => { @@ -358,7 +358,7 @@ describe("Database Handler", () => { }); it("should remove existent input answers", (done) => { - const queryString: string = "DELETE FROM input_answer WHERE id=15 OR id=16;"; + const queryString: string = "DELETE FROM input_answer WHERE id=18 OR id=19;"; const query: QueryOptions = {query: queryString, parameters: []}; dbhandler.executeQuery(query, (err: Error, result?: QueryResult) => { @@ -573,8 +573,8 @@ describe("Read and Write on Database", () => { dbhandler.writeFormAnswer(formAnswer, (err: Error, formAnswerResult: FormAnswer) => { expect(err).to.be.a("null"); - expect(formAnswerResult.id).to.be.equal(7); - let inputAnswerId: number = 15; + expect(formAnswerResult.id).to.be.equal(8); + let inputAnswerId: number = 18; for (const key of Object.keys(formAnswerResult.inputAnswers)){ for (const inputAnswer of formAnswerResult.inputAnswers[parseInt(key, 10)]){ expect(inputAnswer.id).to.be.equal(inputAnswerId); diff --git a/src/utils/validationError.spec.ts b/src/utils/validationError.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..e70e86c32c425444b514a039a87452919a093d21 --- /dev/null +++ b/src/utils/validationError.spec.ts @@ -0,0 +1,20 @@ +/* + * form-creator-api. RESTful API to manage and answer forms. + * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre + * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + * + * This file is part of form-creator-api. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ diff --git a/src/utils/validationError.ts b/src/utils/validationError.ts new file mode 100644 index 0000000000000000000000000000000000000000..f440f973c472edac87d2f20e45aca7a52ea8d53e --- /dev/null +++ b/src/utils/validationError.ts @@ -0,0 +1,42 @@ +/* + * form-creator-api. RESTful API to manage and answer forms. + * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre + * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + * + * This file is part of form-creator-api. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + + /** + * Parameters used to create a dictionary to uses as an object of erro, returning all validations erros just once + */ + export interface ValidationDict { + /** A key is a identifier of a Input instance, and the string is all invalid messages */ + [key: number]: string; + } + + /** + * ValidationError: Extends Error class + * Has a dict that allow us to know which answer is invalide + */ + export class ValidationError extends Error{ + /** A dict that allows user to know which Input Answer is invalid. */ + public readonly validationDict: ValidationDict; + + constructor(validationDict: ValidationDict, ...params: any[]){ + super(...params); + this.validationDict = validationDict; + } + } diff --git a/src/utils/validationHandler.spec.ts b/src/utils/validationHandler.spec.ts index 19eba33344bf5ad11ab4295a71d6debbd032a492..d526f647145ab5483979a418195556e42a3bbfda 100644 --- a/src/utils/validationHandler.spec.ts +++ b/src/utils/validationHandler.spec.ts @@ -20,84 +20,168 @@ */ import { expect } from "chai"; -import { Input, InputOptions, Validation } from "../core/input"; +import { Form } from "../core/form"; +import { FormAnswer, FormAnswerOptions } from "../core/formAnswer"; +import { InputAnswerOptions, InputAnswerOptionsDict } from "../core/inputAnswer"; +import { configs } from "./config"; +import { DbHandler } from "./dbHandler"; import { EnumHandler, InputType, ValidationType } from "./enumHandler"; import { OptHandler } from "./optHandler"; -import {ValidationHandler } from "./validationHandler"; +import { ValidationHandler } from "./validationHandler"; describe("Validation Handler", () => { - it("should test when Input is mandatory", () => { + const dbhandler = new DbHandler(configs.poolconfig); - const inputObj: InputOptions = { - placement: 0 - , description: "Description" - , question: "Question" - , type: InputType.TEXT - , validation: [ - { type: ValidationType.MANDATORY, arguments: [] } - ] + it("should test when Input has a minimum char number", (done) => { + const inputAnswersOpt1: InputAnswerOptions = { + idInput: 4 + , placement: 0 + , value: "MIN 8" + }; + const inputAnswersOpt2: InputAnswerOptions = { + idInput: 5 + , placement: 0 + , value: "Answer to Question 2 Form 2" + }; + const inputAnswerOptionsDict: InputAnswerOptionsDict = { + 4: [inputAnswersOpt1] + , 5: [inputAnswersOpt2] }; - const input = new Input (OptHandler.input(inputObj)); - expect(ValidationHandler.validateInput(input, "FOOL")).to.be.true; - expect(ValidationHandler.validateInput(input, "")).to.be.false; - expect(ValidationHandler.validateInput(input, null)).to.be.false; - expect(ValidationHandler.validateInput(input, undefined)).to.be.false; + const data: Date = new Date(2019, 6, 4); + dbhandler.readForm(2, (error: Error, form: Form) => { + const formAnswerOptions: FormAnswerOptions = { + form + , timestamp: data + , inputsAnswerOptions: inputAnswerOptionsDict + }; + const formAnswer = new FormAnswer(OptHandler.formAnswer(formAnswerOptions)); + try { + ValidationHandler.validateFormAnswer(formAnswer); + } catch (e) { + expect(e.validationDict["4"]).to.be.equal("Input answer must be greater than 8"); + expect(e.validationDict["5"]).to.be.a("undefined"); + } + done(); + }); }); - it("should test when Input has a regex", () => { - const inputObj: InputOptions = { - placement: 0 - , description: "Description" - , question: "Question" - , type: InputType.TEXT - , validation: [ - { type: ValidationType.REGEX, arguments: ["\\d{5}-\\d{3}"] } - ] + it("should test when Input is mandatory", (done) => { + const inputAnswersOpt1: InputAnswerOptions = { + idInput: 4 + , placement: 0 + , value: "Answer to Question 1 Form 2" + }; + const inputAnswersOpt2: InputAnswerOptions = { + idInput: 5 + , placement: 0 + , value: "" + }; + const inputAnswerOptionsDict: InputAnswerOptionsDict = { + 4: [inputAnswersOpt1] + , 5: [inputAnswersOpt2] }; - const input = new Input (OptHandler.input(inputObj)); - expect(ValidationHandler.validateInput(input, "88888-888")).to.be.true; - expect(ValidationHandler.validateInput(input, "88888-88")).to.be.false; - expect(ValidationHandler.validateInput(input, "")).to.be.false; - expect(ValidationHandler.validateInput(input, null)).to.be.false; - expect(ValidationHandler.validateInput(input, undefined)).to.be.false; + + const data: Date = new Date(2019, 6, 4); + dbhandler.readForm(2, (error: Error, form: Form) => { + const formAnswerOptions: FormAnswerOptions = { + form + , timestamp: data + , inputsAnswerOptions: inputAnswerOptionsDict + }; + const formAnswer = new FormAnswer(OptHandler.formAnswer(formAnswerOptions)); + try { + ValidationHandler.validateFormAnswer(formAnswer); + } catch (e) { + expect(e.validationDict["4"]).to.be.a("undefined"); + expect(e.validationDict["5"]).to.be.equal("Input answer is mandatory"); + } + done(); + }); }); - it("should test when Input has a minimum char number", () => { - const inputObj: InputOptions = { - placement: 0 - , description: "Description" - , question: "Question" - , type: InputType.TEXT - , validation: [ - { type: ValidationType.MINCHAR, arguments: ["5"] } - ] + it("should test when Input has a maximum char number", (done) => { + + const inputAnswersOpt1: InputAnswerOptions = { + idInput: 1 + , placement: 0 + , value: "Answer to Question 1 Form 1" + }; + const inputAnswersOpt2: InputAnswerOptions = { + idInput: 2 + , placement: 0 + , value: "12345-000" + }; + const inputAnswersOpt3: InputAnswerOptions = { + idInput: 3 + , placement: 0 + , value: "MORE THEN 10 CHAR" }; - const input = new Input (OptHandler.input(inputObj)); + const inputAnswerOptionsDict: InputAnswerOptionsDict = { + 1: [inputAnswersOpt1] + , 2: [inputAnswersOpt2] + , 3: [inputAnswersOpt3] + }; + const data: Date = new Date(2019, 6, 4); + dbhandler.readForm(1, (error: Error, form: Form) => { + const formAnswerOptions: FormAnswerOptions = { + form + , timestamp: data + , inputsAnswerOptions: inputAnswerOptionsDict + }; + const formAnswer = new FormAnswer(OptHandler.formAnswer(formAnswerOptions)); + try { + ValidationHandler.validateFormAnswer(formAnswer); + } catch (e) { + expect(e.validationDict["1"]).to.be.a("undefined"); + expect(e.validationDict["2"]).to.be.a("undefined"); + expect(e.validationDict["3"]).to.be.equal("Input answer must be lower than 10"); + } + done(); + }); - expect(ValidationHandler.validateInput(input, "12345")).to.be.true; - expect(ValidationHandler.validateInput(input, "123456")).to.be.true; - expect(ValidationHandler.validateInput(input, "1234")).to.be.false; - expect(ValidationHandler.validateInput(input, "")).to.be.false; - expect(ValidationHandler.validateInput(input, null)).to.be.false; - expect(ValidationHandler.validateInput(input, undefined)).to.be.false; }); - it("should test when Input has a maximum char number", () => { - const inputObj: InputOptions = { - placement: 0 - , description: "Description" - , question: "Question" - , type: InputType.TEXT - , validation: [ - { type: ValidationType.MAXCHAR, arguments: ["5"] } - ] + + it("should test when Input has a RegEx", (done) => { + + const inputAnswersOpt1: InputAnswerOptions = { + idInput: 1 + , placement: 0 + , value: "Answer to Question 1 Form 1" + }; + const inputAnswersOpt2: InputAnswerOptions = { + idInput: 2 + , placement: 0 + , value: "12aa345-000" }; - const input = new Input (OptHandler.input(inputObj)); - expect(ValidationHandler.validateInput(input, "1234")).to.be.true; - expect(ValidationHandler.validateInput(input, "12345")).to.be.true; - expect(ValidationHandler.validateInput(input, "")).to.be.true; - expect(ValidationHandler.validateInput(input, "123456")).to.be.false; - expect(ValidationHandler.validateInput(input, null)).to.be.false; - expect(ValidationHandler.validateInput(input, undefined)).to.be.false; + const inputAnswersOpt3: InputAnswerOptions = { + idInput: 3 + , placement: 0 + , value: "MAXCHAR 10" + }; + const inputAnswerOptionsDict: InputAnswerOptionsDict = { + 1: [inputAnswersOpt1] + , 2: [inputAnswersOpt2] + , 3: [inputAnswersOpt3] + }; + const data: Date = new Date(2019, 6, 4); + dbhandler.readForm(1, (error: Error, form: Form) => { + const formAnswerOptions: FormAnswerOptions = { + form + , timestamp: data + , inputsAnswerOptions: inputAnswerOptionsDict + }; + const formAnswer = new FormAnswer(OptHandler.formAnswer(formAnswerOptions)); + try { + ValidationHandler.validateFormAnswer(formAnswer); + } catch (e) { + expect(e.validationDict["1"]).to.be.a("undefined"); + expect(e.validationDict["3"]).to.be.a("undefined"); + expect(e.validationDict["2"]).to.be.equal("RegEx do not match"); + } + done(); + }); + }); + }); diff --git a/src/utils/validationHandler.ts b/src/utils/validationHandler.ts index e2a9371dc2e882146f0b90d8d57609debab0592a..d04a2d4db0c3359b06fc90c7edb63fa3c4683ae6 100644 --- a/src/utils/validationHandler.ts +++ b/src/utils/validationHandler.ts @@ -19,8 +19,10 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ +import { FormAnswer } from "../core/formAnswer"; import { Input } from "../core/input"; import { ValidationType } from "./enumHandler"; +import { ValidationDict, ValidationError } from "./validationError"; /** * Validation's handler. Manage parse validation through the project. @@ -71,30 +73,54 @@ export class ValidationHandler { * Validate if answer has minimum number of chars * @param input - Input to validate answer. * @param answer - Answer of input - * @returns - true if answer is valid according a given Input. + * @returns - A string with all errors. */ - public static validateInput(input: Input, answer: string): boolean{ - let result: boolean = true; - + private static validateInput(input: Input, answer: string): string{ + const errors: string[] = []; for ( const validation of input.validation){ switch (validation.type) { case ValidationType.REGEX: - result = result && this.validateByRegex(answer, validation.arguments[0]); + if (!this.validateByRegex(answer, validation.arguments[0])){ + errors.push("RegEx do not match"); + } break; case ValidationType.MANDATORY: - result = result && this.validateMandatory(answer); + if (!(this.validateMandatory(answer))){ + errors.push("Input answer is mandatory"); + } break; case ValidationType.MAXCHAR: - result = result && this.validateMaxChar(answer, validation.arguments[0]); + if (!(this.validateMaxChar(answer, validation.arguments[0]))){ + errors.push("Input answer must be lower than " + validation.arguments[0]); + } break; case ValidationType.MINCHAR: - result = result && this.validateMinChar(answer, validation.arguments[0]); + if (!(this.validateMinChar(answer, validation.arguments[0]))){ + errors.push("Input answer must be greater than " + validation.arguments[0]); + } break; } } + return errors.join(";"); + + } + + public static validateFormAnswer(formAnswer: FormAnswer): void{ + const errorsDict: ValidationDict = {}; + + for ( const input of formAnswer.form.inputs){ + for (const answer of formAnswer.inputAnswers[input.id]){ + const error: string = this.validateInput(input, answer.value); + if (error !== "" && error !== undefined){ + errorsDict[input.id] = error; + } + } + } - return result; + if ( Object.keys(errorsDict).length > 0){ + throw new ValidationError(errorsDict, "Validation Error"); + } } }