import { mount } from 'enzyme'; import type { FormikProps } from 'formik/dist/types'; import React from 'react'; import type { IFormInputProps } from '../..'; import { FormikFormField, FormikSpelContextProvider, ReactSelectInput, SpelToggle, SpinFormik, TextAreaInput, TextInput, } from '../..'; const makeSpy = () => { const renderSpy = jasmine.createSpy('render'); const inputProps = () => renderSpy.calls.mostRecent().args[0] as IFormInputProps; const InputSpy = (props: any) => { renderSpy(props); return ; }; return { inputProps, renderSpy, InputSpy }; }; const asyncTick = () => new Promise((resolve) => setTimeout(resolve)); describe('', () => { it(`renders the input`, () => { const { renderSpy, InputSpy } = makeSpy(); mount( } />); expect(renderSpy).toHaveBeenCalled(); }); it(`passes the field name to the input`, () => { const { inputProps, InputSpy } = makeSpy(); mount( } />); expect(inputProps().name).toBe('foo.bar'); }); it(`passes the field value to the input using the 'name' as an identifier`, () => { const { inputProps, InputSpy } = makeSpy(); const initialValues = { foo: { bar: 'abc123' } }; mount( } />); expect(inputProps().value).toBe('abc123'); }); it(`passes validation information to the input`, async () => { const { inputProps, InputSpy } = makeSpy(); const initialValues = { foo: { bar: 'abc123' } }; const validate = () => ({ foo: { bar: 'bad' } }); mount( } />, ); await asyncTick(); expect(inputProps().validation.messageNode).toBe('bad'); expect(inputProps().validation.category).toBe('error'); }); it(`does not index into strings for errors`, async () => { const { inputProps, InputSpy } = makeSpy(); const initialValues = { foo: { bar: ['abc'] } }; const validate = () => ({ foo: { bar: 'bad' } }); mount( } />, ); await asyncTick(); expect(inputProps().value).toBe('abc'); // in errors, foo.bar[0] error should be null, not 'b' expect(inputProps().validation.messageNode).toBe(null); expect(inputProps().validation.category).toBe(null); }); describe('SpEL-awareness', () => { const AccountField = (props: { propsSpelAware?: boolean }) => ( } spelAware={props.propsSpelAware} /> ); it('Renders a SpelToggle action button when appropriate based on context and props', () => { const contextAndPropConfigs: Array & { renderSpelToggle: number }> = [ { propsSpelAware: false, renderSpelToggle: 0, }, { contextSpelAware: false, renderSpelToggle: 0, }, { contextSpelAware: true, propsSpelAware: false, renderSpelToggle: 0, }, { propsSpelAware: true, renderSpelToggle: 1, }, { contextSpelAware: true, renderSpelToggle: 1, }, { contextSpelAware: false, propsSpelAware: true, renderSpelToggle: 1, }, ]; contextAndPropConfigs.forEach((config) => { const component = mount( } />, ); expect(component.find(SpelToggle).length).toEqual(config.renderSpelToggle); }); }); it('renders a freeform input by default if the field value is SpEL and freeform SpEL inputs are enabled', () => { const component = mount( } />, ); expect(component.find(TextAreaInput).length).toEqual(1); expect(component.find(ReactSelectInput).length).toEqual(0); }); it('does not render the input even once if the field value is SpEL and freeform SpEL inputs are enabled', () => { const spy = jasmine.createSpy(); const NeverRenderedComponent = () => { spy(); return ; }; const TestField = () => ( ); mount( } />); expect(spy).not.toHaveBeenCalled(); }); it('renders the default input if the field value is not SpEL', () => { const component = mount( } />, ); component.setProps({}); expect(component.find(ReactSelectInput).length).toEqual(1); expect(component.find(TextAreaInput).length).toEqual(0); }); it('clicking the SpelToggle switches the input type from default to freeform and clears the field value', () => { const component = mount( } />, ); expect(component.find(ReactSelectInput).length).toEqual(1); expect(component.find(TextAreaInput).length).toEqual(0); expect(component.find(ReactSelectInput).prop('value')).toEqual('my-account'); component.find(SpelToggle).simulate('click'); expect(component.find(ReactSelectInput).length).toEqual(0); expect(component.find(TextAreaInput).length).toEqual(1); expect(component.find(TextAreaInput).prop('value')).toEqual(null); }); it('clicking the SpelToggle switches the input type from freeform to default and clears the field value', () => { const component = mount( } />, ); expect(component.find(ReactSelectInput).length).toEqual(0); expect(component.find(TextAreaInput).length).toEqual(1); expect(component.find(TextAreaInput).prop('value')).toEqual('${spel_account}'); component.find(SpelToggle).simulate('click'); expect(component.find(ReactSelectInput).length).toEqual(1); expect(component.find(TextAreaInput).length).toEqual(0); expect(component.find(ReactSelectInput).prop('value')).toEqual(null); }); }); }); interface ITestFormWrapperProps { render: (props: FormikProps) => React.ReactNode; validate?: (form: any) => any; initialValues?: any; contextSpelAware?: boolean; propsSpelAware?: boolean; } function Test(props: ITestFormWrapperProps) { return ( ({}))} onSubmit={() => {}} render={props.render} /> ); }