-
Notifications
You must be signed in to change notification settings - Fork 11
Add enable_when attribute to the input #758
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
base: main
Are you sure you want to change the base?
Changes from 12 commits
a1b40a2
c3bb5f9
0b17e40
8d004a6
098bda9
87e3a29
983a165
01b1a04
bbf9490
e1913e4
1de06b6
77fff3b
ebf97db
4cf6082
f81cbaf
a3cd415
7810955
33b30e3
a27cff2
aaaf1e2
323298d
73af7d3
e7fba3c
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,54 @@ | ||
| import { describe, expect, it } from 'vitest'; | ||
| import { normalizeValue } from '~/components/InputsModal/InputHelpers'; | ||
|
|
||
| describe('normalizeValue', () => { | ||
| it('returns empty string for null', () => { | ||
| expect(normalizeValue(null)).toBe(''); | ||
| }); | ||
|
|
||
| it('returns empty string for undefined', () => { | ||
| expect(normalizeValue(undefined)).toBe(''); | ||
| }); | ||
|
|
||
| it('returns string unchanged', () => { | ||
| expect(normalizeValue('')).toBe(''); | ||
| expect(normalizeValue('hello')).toBe('hello'); | ||
| expect(normalizeValue('4.0')).toBe('4.0'); | ||
| }); | ||
|
|
||
| it('converts number to string', () => { | ||
| expect(normalizeValue(0)).toBe('0'); | ||
| expect(normalizeValue(42)).toBe('42'); | ||
| expect(normalizeValue(-1)).toBe('-1'); | ||
| expect(normalizeValue(3.14)).toBe('3.14'); | ||
| }); | ||
|
|
||
| it('converts boolean to string', () => { | ||
| expect(normalizeValue(true)).toBe('true'); | ||
| expect(normalizeValue(false)).toBe('false'); | ||
| }); | ||
|
|
||
| it('converts bigint to string', () => { | ||
| expect(normalizeValue(BigInt(0))).toBe('0'); | ||
| expect(normalizeValue(BigInt(9007199254740991))).toBe('9007199254740991'); | ||
| }); | ||
|
|
||
| it('converts symbol to string', () => { | ||
| const sym = Symbol('test'); | ||
| expect(normalizeValue(sym)).toBe(sym.toString()); | ||
| }); | ||
|
|
||
| it('JSON-stringifies plain objects', () => { | ||
| expect(normalizeValue({})).toBe('{}'); | ||
| expect(normalizeValue({ a: 1, b: 'x' })).toBe('{"a":1,"b":"x"}'); | ||
| }); | ||
|
|
||
| it('JSON-stringifies arrays', () => { | ||
| expect(normalizeValue([])).toBe('[]'); | ||
| expect(normalizeValue([1, 'a', true])).toBe('[1,"a",true]'); | ||
| }); | ||
|
|
||
| it('returns empty string for function (default case)', () => { | ||
| expect(normalizeValue(() => {})).toBe(''); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,7 @@ | |
| import InputTextField from '~/components/InputsModal/InputTextField'; | ||
| import { isJsonString } from '~/components/InputsModal/InputHelpers'; | ||
| import ThemeProvider from '~/components/ThemeProvider'; | ||
| import InputFields from '../InputFields'; | ||
|
|
||
| describe('Input Components', () => { | ||
| it('renders InputCheckboxGroup', () => { | ||
|
|
@@ -180,4 +181,141 @@ | |
| expect(isJsonString(string)).toEqual(true); | ||
| }); | ||
| }); | ||
|
|
||
| describe('renders conditional fields correctly', () => { | ||
| const constructInput = (props: Partial<TestInput>): TestInput => { | ||
| return { | ||
| name: props?.name || '', | ||
| type: (props?.type || 'text') as TestInput['type'], | ||
| title: props?.title, | ||
| optional: props?.optional, | ||
| enable_when: props?.enable_when, | ||
| hidden: props?.hidden, | ||
| value: props?.value, | ||
| }; | ||
| }; | ||
|
|
||
| const constructInputsMap = (inputs: TestInput[]): Map<string, string> => { | ||
| return inputs.reduce((acc, input) => { | ||
| acc.set(input.name, input.value as string); | ||
| return acc; | ||
| }, new Map<string, string>()); | ||
| }; | ||
|
|
||
| const renderInputFields = (inputs: TestInput[], inputsMap: Map<string, string>) => { | ||
| render( | ||
| <ThemeProvider> | ||
| <SnackbarProvider> | ||
| <InputFields inputs={inputs} inputsMap={inputsMap} setInputsMap={() => {}} /> | ||
| </SnackbarProvider> | ||
| </ThemeProvider>, | ||
| ); | ||
| }; | ||
|
|
||
| const assertInputVisibility = (inputs: Partial<TestInput>[], expectedVisible: boolean[]) => { | ||
| const constructedInputs: TestInput[] = inputs.map((input) => constructInput(input)); | ||
| const inputsMap = constructInputsMap(constructedInputs); | ||
| renderInputFields(constructedInputs, inputsMap); | ||
|
|
||
| constructedInputs.forEach((input, index) => { | ||
| const label = input.title as string; | ||
| const shouldBeVisible = expectedVisible[index]; | ||
| if (shouldBeVisible) { | ||
| expect(screen.getByLabelText(label, { exact: false })).toBeVisible(); | ||
| } else { | ||
| expect(screen.queryByLabelText(label, { exact: false })).not.toBeInTheDocument(); | ||
| } | ||
| }); | ||
| }; | ||
|
|
||
| it('renders field when it has no enable_when (always visible)', () => { | ||
| assertInputVisibility([{ name: 'standalone', title: 'Standalone field' }], [true]); | ||
| }); | ||
|
|
||
| it('skips rendering dependent field when controlling value is undefined', () => { | ||
| assertInputVisibility( | ||
| [ | ||
| { name: 'trigger', title: 'Trigger' }, | ||
| { | ||
| name: 'dependent', | ||
| title: 'Dependent', | ||
| enable_when: { input_name: 'trigger', value: 'yes' }, | ||
| }, | ||
| ], | ||
| [true, false], | ||
| ); | ||
| }); | ||
|
|
||
| it('skips rendering when controlling value does not match enable_when', () => { | ||
| assertInputVisibility( | ||
| [ | ||
| { name: 'trigger', title: 'Trigger', value: 'no' }, | ||
| { | ||
| name: 'dependent', | ||
| title: 'Dependent', | ||
| enable_when: { input_name: 'trigger', value: 'yes' }, | ||
| }, | ||
| ], | ||
| [true, false], | ||
| ); | ||
| }); | ||
|
|
||
| it('renders dependent field when controlling value matches enable_when', () => { | ||
| assertInputVisibility( | ||
| [ | ||
| { name: 'trigger', title: 'Trigger', value: 'yes' }, | ||
| { | ||
| name: 'dependent', | ||
| title: 'Dependent', | ||
| enable_when: { input_name: 'trigger', value: 'yes' }, | ||
| }, | ||
| ], | ||
| [true, true], | ||
| ); | ||
| }); | ||
|
|
||
| it('hides field when hidden is true even if enable_when would pass', () => { | ||
| assertInputVisibility( | ||
| [ | ||
| { name: 'trigger', title: 'Trigger', value: 'yes' }, | ||
| { | ||
| name: 'dependent', | ||
| title: 'Dependent', | ||
| enable_when: { input_name: 'trigger', value: 'yes' }, | ||
| hidden: true, | ||
| }, | ||
| ], | ||
| [true, false], | ||
| ); | ||
| }); | ||
|
|
||
| it('renders dependent field when controlling value (array) equals enable_when array value', () => { | ||
| const refValue = ['a', 'b']; | ||
| const inputs: TestInput[] = [ | ||
| constructInput({ | ||
| name: 'trigger', | ||
| title: 'Trigger', | ||
| type: 'checkbox', | ||
| value: refValue, | ||
| }), | ||
| constructInput({ | ||
| name: 'dependent', | ||
| title: 'Dependent', | ||
| enable_when: { input_name: 'trigger', value: ['a', 'b'] }, | ||
|
Contributor
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. should the value be a string rep of the Array? Or is use with checkboxes disallowed? |
||
| }), | ||
| ]; | ||
| const inputsMap = new Map<string, unknown>(); | ||
| inputsMap.set('trigger', refValue); | ||
| render( | ||
| <ThemeProvider> | ||
| <SnackbarProvider> | ||
| <InputFields inputs={inputs} inputsMap={inputsMap} setInputsMap={() => {}} /> | ||
| </SnackbarProvider> | ||
| </ThemeProvider>, | ||
| ); | ||
|
|
||
| expect(screen.getByRole('checkbox', { name: /Trigger/i })).toBeInTheDocument(); | ||
| expect(screen.getByRole('textbox', { name: /Dependent/i })).toBeVisible(); | ||
| }); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -140,6 +140,10 @@ export interface TestInput { | |
| list_options?: InputOption[]; | ||
| mode?: string; | ||
| }; | ||
| enable_when?: { | ||
|
Contributor
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 propose updated Inferno documentation in this section (rendered here) for this input feature.
Author
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. |
||
| input_name: string; | ||
| value: string; | ||
| }; | ||
| } | ||
|
|
||
| export interface TestOutput { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.