yahoo / jafar

🌟!(Just another form application renderer)
https://yahoo.github.io/jafar
MIT License
109 stars 9 forks source link

Add component mapper util #86

Closed galhavivi closed 4 years ago

galhavivi commented 4 years ago

To use existing components library in a form (such as Material UI) - a map from the Jafar component generic props to the existing component props is needed.

Example - mapping props using react functional component

/* Input.js */
import React from 'react';
import Input from '@material-ui/core/Input';

export default ({ value = '', state = {}, disabled = false, onValueChange }) => <Input
  type={state.type}
  placeholder={state.placeholder}
  value={value}
  disabled={disabled}
  onChange={(e) => onValueChange(e.target.value)}
/>

Example - mapping props using a desired toJafar HOC

/* Input.js */
import { toJafar } from '@jafar/react-components/utils';
import Input from '@material-ui/core/Input';

export const mapper = ({ value = '', disabled = false, state = {}, onValueChange }) => ({
  type: state.type
  placeholder: state.placeholder,
  value,
  disabled,
  onChange: (e) => onValueChange(e.target.value),
});

export default toJafar(Input, mapper);

Using the above HOC saves the react import as well as simplify tests. The following code tests mapper function with a simple javascript test.

/* Input.spec.js */
import React from 'react';
import { shallow } from 'enzyme';
import Input, { mapper } from './Input.js';

describe('Input', () => {
  const jafarProps = {
    state: {
      type: 'text',
      placeholder: 'Enter name...',
    },
    value: 'Rachel',
    disabled: false,
    onValueChange: jest.fn(),
  };

  const expectedInputProps = {
    type: 'text',
    placeholder: 'Enter name...',
    value: 'Rachel Green',
    disabled: false,
    onChange: expect.any(Function),
  };

  let inputProps;

  beforeEach(() => {
    inputProps = mapper(jafarProps);
  });

  describe('mapper', () => {
    it('return correct props', () => {
      expect(inputProps).toEqual(expectedInputProps);
    });

    it('call onValueChange with correct value', () => {
      const mockEvent = { target: { value: 'Ross' } };
      inputProps.onChange(mockEvent);
      expect(jafarProps.onValueChange).toHaveBeenCalledWith('Ross');
    });
  });

  describe('component', () => {
    it('renders ok', () => {
      const component = shallow(<Input {...jafarProps} />);
      expect(component.props()).toEqual(expectedInputProps);
    });
  });
});