Repository: vazco/uniforms (ts)

Issue:
JSONSchema bridge fails on object that is using allOf + #ref
<!--
  Before you open an issue, please check if a similar one already exists or has been closed before.
  We will be grateful for using our reproduction sandbox available at
  https://codesandbox.io/s/github/vazco/uniforms/tree/master/reproductions
  whenever a code sample is presented for debugging purposes.
-->

When adding the following test in `packages/uniforms-bridge-json-schema/__tests__/JSONSchemaBridge.ts`:
```js
    it('returns correct definition (allOf with $ref)', () => {
      expect(bridge.getField('shippingAddress.street')).toEqual({
        type: 'string',
      });
    });
```
It fails with:
```Summary of all failing tests
 FAIL  packages/uniforms-bridge-json-schema/__tests__/JSONSchemaBridge.ts
  ● JSONSchemaBridge › #getField › returns correct definition (allOf with $ref)

    Invariant Violation: Field not found in schema: "shippingAddress.street"

      162 |       }
      163 | 
    > 164 |       invariant(definition, 'Field not found in schema: "%s"', name);
          |       ^
      165 | 
      166 |       if (definition.$ref) {
      167 |         definition = resolveRef(definition.$ref, this.schema);

      at invariant (node_modules/invariant/invariant.js:40:15)
      at packages/uniforms-bridge-json-schema/src/JSONSchemaBridge.ts:164:7
          at Array.reduce (<anonymous>)
      at JSONSchemaBridge.reduce [as getField] (packages/uniforms-bridge-json-schema/src/JSONSchemaBridge.ts:123:33)
      at Object.getField (packages/uniforms-bridge-json-schema/__tests__/JSONSchemaBridge.ts:334:21)

```
I expect it to work and also see this happen while trying to implement uniform with a schema generated by [pydantic](pydantic-docs.helpmanual.io)

Pull request:
Added JSONSchemaBridge getField resolve to $ref definition inside allOf.
Fixed unexpected behavior described in #722.

Closes #722.

Patch:
diff --git a/packages/uniforms-bridge-json-schema/src/JSONSchemaBridge.ts b/packages/uniforms-bridge-json-schema/src/JSONSchemaBridge.ts
index 2ea8cc83..0afaf63e 100644
--- a/packages/uniforms-bridge-json-schema/src/JSONSchemaBridge.ts
+++ b/packages/uniforms-bridge-json-schema/src/JSONSchemaBridge.ts
@@ -154,9 +154,14 @@ export default class JSONSchemaBridge extends Bridge {
           'oneOf',
         ]
           .filter(key => definition[key])
-          .map(key =>
-            definition[key].find(({ properties = {} }) => properties[next]),
-          );
+          .map(key => {
+            const localDef = definition[key].map(subSchema =>
+              subSchema.$ref
+                ? resolveRef(subSchema.$ref, this.schema)
+                : subSchema,
+            );
+            return localDef.find(({ properties = {} }) => properties[next]);
+          });
 
         definition = combinedDefinition[next];
       }


Test patch:
diff --git a/packages/uniforms-bridge-json-schema/__tests__/JSONSchemaBridge.ts b/packages/uniforms-bridge-json-schema/__tests__/JSONSchemaBridge.ts
index 21e372b3..ebae1dd3 100644
--- a/packages/uniforms-bridge-json-schema/__tests__/JSONSchemaBridge.ts
+++ b/packages/uniforms-bridge-json-schema/__tests__/JSONSchemaBridge.ts
@@ -369,6 +369,40 @@ describe('JSONSchemaBridge', () => {
         /Field not found in schema/,
       );
     });
+
+    it('throws when resolving field schema is not possible (with allOf with $ref field)', () => {
+      expect(() => bridge.getField('shippingAddress.street.invalid')).toThrow(
+        /Field not found in schema/,
+      );
+    });
+
+    it('throws when resolving field schema is not possible (with allOf with $ref field without properties prop)', () => {
+      const localBridge = new JSONSchemaBridge(
+        {
+          definitions: schema.definitions,
+          properties: {
+            container: {
+              allOf: [
+                {
+                  required: ['type'],
+                },
+              ],
+            },
+          },
+        },
+        validator,
+      );
+
+      expect(() => localBridge.getField('container.invalid')).toThrow(
+        /Field not found in schema/,
+      );
+    });
+
+    it('returns correct definition (allOf with $ref)', () => {
+      expect(bridge.getField('shippingAddress.street')).toEqual({
+        type: 'string',
+      });
+    });
   });
 
   describe('#getInitialValue', () => {