diff --git a/packages/api-explorer/__tests__/__fixtures__/polymorphism/discriminators.json b/packages/api-explorer/__tests__/__fixtures__/polymorphism/discriminators.json index 9a11535a6..984dbc2b0 100644 --- a/packages/api-explorer/__tests__/__fixtures__/polymorphism/discriminators.json +++ b/packages/api-explorer/__tests__/__fixtures__/polymorphism/discriminators.json @@ -72,6 +72,44 @@ } } }, + "/oneOfWithImproperlyPlacedDiscriminator": { + "patch": { + "summary": "oneOf with a discriminator that is referencing a property up a level", + "description": "This is an improper use of discriminators, but we should ignore the discriminator if this happens instead of failing to render the operation.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "connector_type": { + "type": "string", + "enum": [ + "s3Import", + "gcsImport" + ] + }, + "connector_properties": { + "type": "object", + "oneOf": [ + { + "$ref": "#/components/schemas/gcsImport" + }, + { + "$ref": "#/components/schemas/s3Import" + } + ], + "discriminator": { + "propertyName": "connector_type" + } + } + } + } + } + } + } + } + }, "/pets": { "patch": { "summary": "oneOf request with a nested allOf and embedded discriminator", @@ -359,6 +397,28 @@ } } ] + }, + "gcsImport": { + "type": "object", + "properties": { + "gcs_bucket": { + "type": "string" + }, + "gcs_prefix": { + "type": "string" + } + } + }, + "s3Import": { + "type": "object", + "properties": { + "s3_bucket": { + "type": "string" + }, + "s3_prefix": { + "type": "string" + } + } } } } diff --git a/packages/api-explorer/__tests__/form-components/MultiSchemaField.test.jsx b/packages/api-explorer/__tests__/form-components/MultiSchemaField.test.jsx index f50f959ce..c57c82ef9 100644 --- a/packages/api-explorer/__tests__/form-components/MultiSchemaField.test.jsx +++ b/packages/api-explorer/__tests__/form-components/MultiSchemaField.test.jsx @@ -194,4 +194,19 @@ describe('discriminator', () => { expect(secondChangeParamsText).toContain('bark'); expect(secondChangeParamsText).not.toContain('hunts'); }); + + it('should ignore the discriminator if it is improperly placed', async () => { + const testOas = new Oas(discriminators); + await testOas.dereference(); + const operation = testOas.operation('/oneOfWithImproperlyPlacedDiscriminator', 'patch'); + const Params = createParams(oas, operation); + + expect(() => { + return mount( +
+ +
+ ); + }).not.toThrow("Cannot use 'in' operator to search for '$ref' in null"); + }); }); diff --git a/packages/api-explorer/src/form-components/MultiSchemaField.jsx b/packages/api-explorer/src/form-components/MultiSchemaField.jsx index 8444408db..0621b0ad4 100644 --- a/packages/api-explorer/src/form-components/MultiSchemaField.jsx +++ b/packages/api-explorer/src/form-components/MultiSchemaField.jsx @@ -241,9 +241,10 @@ class MultiSchemaField extends Component { const SchemaField = registry.fields.SchemaField; const { selectedIndex, selectedValue, discriminatorSchema, discriminatorFieldSchema, enumOptions } = this.state; - // We've got a custom path if there's a discriminator, otherwise we fall back ot the old multischema field - if (discriminatorSchema) { - // Find which schema we wnat to render by looking at the options prop. The order of these options matches the + // We've got a custom path if there's a properly-formed discriminator, otherwise we fall back ot the old MultiSchema + // field. + if (discriminatorFieldSchema && discriminatorSchema) { + // Find which schema we want to render by looking at the options prop. The order of these options matches the // order of the dropdown options, and so we can just stick with matching indicies. const option = options[selectedIndex] || null; let optionSchema;