-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: fixes #3692 - simple discriminator now bypasses isValid() calls in getMatchingOption and getClosestMatchingOption for improved performance #3845
Changes from 2 commits
9bd46b7
1141f79
1057b97
794dad5
639c8bd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import get from 'lodash/get'; | ||
import { PROPERTIES_KEY } from './constants'; | ||
import { RJSFSchema, StrictRJSFSchema } from './types'; | ||
|
||
export default function getOptionMatchingSimpleDiscriminator<T = any, S extends StrictRJSFSchema = RJSFSchema>( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add the same documentation you put into the docs above here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
formData: T | undefined, | ||
options: S[], | ||
discriminatorField?: string | ||
): number | undefined { | ||
if (formData && discriminatorField) { | ||
const value = get(formData, discriminatorField); | ||
|
||
if (value === undefined) { | ||
return; | ||
} | ||
|
||
for (let i = 0; i < options.length; i++) { | ||
const option = options[i]; | ||
const discriminator = get(option, [PROPERTIES_KEY, discriminatorField], {}); | ||
|
||
if (discriminator.type === 'object' || discriminator.type === 'array') { | ||
continue; | ||
} | ||
|
||
if (discriminator.const === value) { | ||
return i; | ||
} | ||
|
||
if (discriminator.enum?.includes(value)) { | ||
return i; | ||
} | ||
michal-kurz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
return; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import getOptionMatchingSimpleDiscriminator from '../src/getOptionMatchingSimpleDiscriminator'; | ||
|
||
describe('getOptionMatchingSimpleDiscriminator()', () => { | ||
describe('returns undefined if no option matches discriminator', () => { | ||
test('no options with no data', () => { | ||
expect(getOptionMatchingSimpleDiscriminator({}, [], 'id')).toEqual(undefined); | ||
}); | ||
|
||
test('no options with data', () => { | ||
expect(getOptionMatchingSimpleDiscriminator({ foo: 'foo' }, [], 'id')).toEqual(undefined); | ||
}); | ||
|
||
test('options with no data', () => { | ||
expect( | ||
getOptionMatchingSimpleDiscriminator({}, [{ type: 'object', properties: { foo: { const: 'foo' } } }], 'id') | ||
).toEqual(undefined); | ||
}); | ||
|
||
test('matching property, but no discriminatorField', () => { | ||
expect( | ||
getOptionMatchingSimpleDiscriminator({ foo: 'foo' }, [ | ||
{ type: 'object', properties: { foo: { const: 'foo' } } }, | ||
]) | ||
).toEqual(undefined); | ||
}); | ||
|
||
test('matching property, but different discriminatorField', () => { | ||
expect( | ||
getOptionMatchingSimpleDiscriminator( | ||
{ foo: 'foo' }, | ||
[{ type: 'object', properties: { foo: { const: 'foo' } } }], | ||
'bar' | ||
) | ||
).toEqual(undefined); | ||
}); | ||
}); | ||
|
||
describe('returns option index if option matches discriminator', () => { | ||
test('const discriminator', () => { | ||
expect( | ||
getOptionMatchingSimpleDiscriminator( | ||
{ foo: 'foo' }, | ||
[{}, { type: 'object', properties: { foo: { const: 'foo' } } }], | ||
'foo' | ||
) | ||
).toEqual(1); | ||
}); | ||
|
||
test('enum discriminator', () => { | ||
expect( | ||
getOptionMatchingSimpleDiscriminator( | ||
{ foo: 'foo' }, | ||
[{}, { type: 'object', properties: { foo: { enum: ['bar', 'foo'] } } }], | ||
'foo' | ||
) | ||
).toEqual(1); | ||
}); | ||
}); | ||
Comment on lines
+39
to
+58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps there are some other relevant cases that I'm missing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You just need to figure out the test coverage There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I quite struggled trying to make this description as understandable and straght-forwards as possible.