All files / tests wrap.tsx

100% Statements 16/16
100% Branches 8/8
100% Functions 7/7
100% Lines 15/15

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67                  36x   36x   5x   5x     31x       19x       19x 11x     8x             12x 18x 18x   18x 20x   20x                                            
import { ComponentProps, ElementType, useMemo } from 'react';
 
type BaseComponentFormats<C extends React.ElementType> = C | { Component: C } | { default: C };
 
export type SupportedComponentFormats<C extends React.ElementType> =
  | BaseComponentFormats<C>
  | Promise<BaseComponentFormats<C>>;
 
async function getComponent<C extends React.ElementType>(value: SupportedComponentFormats<C>): Promise<C> {
  const response = await value;
 
  if (typeof response === 'object') {
    // TODO: Is there a better way to do this?
    const value = response as any;
 
    return value.default ?? value.Component;
  }
 
  return response;
}
 
function isComponentProps<P extends ComponentProps<any>>(props?: P | (() => P)): props is P {
  return !props || typeof props === 'object';
}
 
function getComponentProps<P extends ComponentProps<any>>(props?: P | (() => P)): P {
  if (isComponentProps(props)) {
    return props;
  }
 
  return props();
}
 
export function wrap<WC extends ElementType>(
  wrappedComponent: SupportedComponentFormats<WC>,
  wrappedProps?: Omit<ComponentProps<WC>, 'children'> | (() => Omit<ComponentProps<WC>, 'children'>)
) {
  return async <C extends React.ElementType>(component: SupportedComponentFormats<C>) => {
    const WrappedComponent: any = await getComponent(wrappedComponent);
    const Component = await getComponent(component);
 
    return (props: ComponentProps<C>) => {
      const outerProps = useMemo(() => getComponentProps(wrappedProps), []);
 
      return <WrappedComponent {...outerProps} children={<Component {...props} />} />;
    };
  };
}
 
// For some reason its marking the namespace as untested... ?
/* c8 ignore start */
export namespace wrap {
  /* c8 ignore end */
  export function concat(...wrappers: ReturnType<typeof wrap>[]): ReturnType<typeof wrap> {
    return async <C extends React.ElementType>(component: SupportedComponentFormats<C>) => {
      let result;
 
      // TODO: Figure out if this can be generated per concater rather then per component
      for (const wrapper of wrappers) {
        result = result ? wrapper(result) : wrapper(component);
      }
 
      return result;
    };
  }
}