Repository: icebob/fastest-validator
Pull request #111 (2020-02-08 17:16:43)

Fix string with pattern where regular expression contains a double quote
For the string rule with pattern, if the regular expression contains a double quote an invalid token error occurs in the message field.  This is because the RegExp.toString does not escape the internal double quote and the construction of the message concatenates double quotes to this value.  

You can test this with sample regular expression /^[a-z0-9 .\-'?!":;\\/,_]+$/i

In this pull request, when constructing the message I replace the double quote with an escaped version, but due to the internal processing I have to also escape the escape character (\\\").

Jest reports 100% success for all tests plus the additional test I added.


Patch:
diff --git a/lib/rules/string.js b/lib/rules/string.js
index 6f3aafc..c15a1d9 100644
--- a/lib/rules/string.js
+++ b/lib/rules/string.js
@@ -137,7 +137,7 @@ module.exports = function checkString({ schema, messages }, path, context) {
 
 		src.push(`
 			if (!${pattern.toString()}.test(value))
-				${this.makeError({ type: "stringPattern", expected: "\"" + pattern.toString() + "\"", actual: "origValue", messages })}
+				${this.makeError({ type: "stringPattern", expected: "\"" + pattern.toString().replace('"', "\\\"") + "\"", actual: "origValue", messages })}
 		`);
 	}
 


Test patch:
diff --git a/test/rules/string.spec.js b/test/rules/string.spec.js
index 34461c5..3dbf851 100644
--- a/test/rules/string.spec.js
+++ b/test/rules/string.spec.js
@@ -62,6 +62,13 @@ describe("Test rule: string", () => {
 		expect(check("JOHN")).toEqual(true);
 	});
 
+	it('check pattern with a quote', () => {
+		const check = v.compile({ $$root: true, type: 'string', pattern: /^[a-z0-9 .\-'?!":;\\/,_]+$/i });
+
+		expect(check('John^')).toEqual([{ field: undefined, type: 'stringPattern', expected: '/^[a-z0-9 .\-\'?!":;\\/,_]+$/i', actual: 'John^', message: 'The \'\' field fails to match the required pattern.' }]);
+		expect(check('JOHN')).toEqual(true);
+	});
+
 	it("check contains", () => {
 		const check = v.compile({ $$root: true, type: "string", contains: "bob" });
 
diff --git a/test/typescript/rules/string.spec.ts b/test/typescript/rules/string.spec.ts
index 7c0906a..576d1e6 100644
--- a/test/typescript/rules/string.spec.ts
+++ b/test/typescript/rules/string.spec.ts
@@ -64,7 +64,14 @@ describe('TypeScript Definitions', () => {
             expect(check('JOHN')).toEqual(true);
         });
 
-        it('check contains', () => {
+		it('check pattern with a quote', () => {
+			const check = v.compile({ $$root: true, type: 'string', pattern: /^[a-z0-9 .\-'?!":;\\/,_]+$/i } as RuleString);
+
+			expect(check('John^')).toEqual([{ field: undefined, type: 'stringPattern', expected: '/^[a-z0-9 .\-\'?!":;\\/,_]+$/i', actual: 'John^', message: 'The \'\' field fails to match the required pattern.' }]);
+			expect(check('JOHN')).toEqual(true);
+		});
+
+		it('check contains', () => {
             const check = v.compile({ $$root: true, type: 'string', contains: 'bob' });
 
             expect(check('John')).toEqual([{ type: 'stringContains', expected: 'bob', actual: 'John', message: 'The \'\' field must contain the \'bob\' text.' }]);