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}
/>
);
}