import * as React from 'react';
import {
  shallow,
  mount,
  ShallowWrapper,
  ReactWrapper,
  configure,
} from 'enzyme';
import defaultsDeep from 'lodash-es/defaultsDeep';

const Adapter = require('enzyme-adapter-react-16');
configure({ adapter: new Adapter() });

type ReactTypesWithProps<T> =
  | React.ComponentClass<T>
  | React.StatelessComponent<T>;

interface PartialPropWrapperOpts {
  children?: React.ReactNode;
}

interface PartialPropShallowWrapperOpts extends PartialPropWrapperOpts {
  disableLifecycleMethods?: boolean;
}

export function partialPropShallowWrapper<T>(
  Component: ReactTypesWithProps<T>,
  defaultProps: T,
  opts: PartialPropShallowWrapperOpts = {},
): (customProps?: DeepPartial<T>) => ShallowWrapper<T, {}> {
  return (customProps: DeepPartial<T> = {}) =>
    (shallow as any)(
      <Component {...defaultsDeep(customProps, defaultProps) as T}>
        {opts.children}
      </Component>,
      { disableLifecycleMethods: opts.disableLifecycleMethods },
    );
}

export function partialPropMountWrapper<T>(
  Component: ReactTypesWithProps<T>,
  defaultProps: T,
  opts: PartialPropWrapperOpts = {},
): (customProps?: DeepPartial<T>) => ReactWrapper<T, {}> {
  return (customProps: DeepPartial<T> = {}) =>
    mount(
      <Component {...defaultsDeep(customProps, defaultProps) as T}>
        {opts.children}
      </Component>,
    );
}
