Repository: jquense/yup (ts)

Issue:
Wrong path in ValidationError when validating an object with dotted keys
When validating an object with dotted keys (e.g. `{foo: {'bar.baz': 'zot'}}`) any thrown ValidationErrors will have a `path` that can't be used with things like lodash's `get`, and that will confuse e.g. Formik's error handling.

Example here: https://runkit.com/espenhw/5ce6a57a7e042f001a056407 - I'd like the `path` on the ValidationError to be `a["b.c"]`.

Pull request description:
Use the alternate object index path syntax if the key contains dots
This fixes #536 by switching to the `foo.bar["baz"]` syntax if the key contains a dot.

Alternatively, that syntax could be used unconditionally; I chose not to so as to keep the path pretty when possible.

There are, of course, other characters that would break the path syntax, e.g. square brackets and quotes.  The current approach would work for anything but double quotes; I'm not familiar enough with lodash's path syntax to come up with something that would always work.

Patch:
diff --git a/src/object.js b/src/object.js
index fdd5110..c624cb4 100644
--- a/src/object.js
+++ b/src/object.js
@@ -146,7 +146,10 @@ inherits(ObjectSchema, MixedSchema, {
         originalValue = originalValue || value;
 
         let validations = this._nodes.map(key => {
-          let path = makePath`${opts.path}.${key}`;
+          let path =
+            key.indexOf('.') === -1
+              ? makePath`${opts.path}.${key}`
+              : makePath`${opts.path}["${key}"]`;
           let field = this.fields[key];
 
           let innerOptions = {


Test patch:
diff --git a/test/object.js b/test/object.js
index 705067f..35db472 100644
--- a/test/object.js
+++ b/test/object.js
@@ -504,6 +504,27 @@ describe('Object types', () => {
       }
     });
 
+    it('should set the correct path with dotted keys', async () => {
+      let inst = object({
+        'dotted.str': string()
+          .required()
+          .nullable(),
+        nested: lazy(() => inst.default(undefined)),
+      });
+
+      let value = {
+        nested: { 'dotted.str': null },
+        'dotted.str': 'foo',
+      };
+
+      try {
+        await inst.validate(value, { strict: true });
+      } catch (err) {
+        err.path.should.equal('nested["dotted.str"]');
+        err.message.should.match(/required/);
+      }
+    });
+
     it('should resolve array sub types', async () => {
       let inst = object({
         str: string()