From 3fb47bb082a6eb81fc06e5e69201e9f3bcd7b565 Mon Sep 17 00:00:00 2001 From: Tan90Qian <1436811949@qq.com> Date: Tue, 2 Jul 2019 04:01:34 +0800 Subject: [PATCH] fix enzyme's ShallowRendererProps interface (#36442) * fix enzyme's ShallowRendererProps interface * fix for ci * update test case for wrappingComponent * fix for ci * fix for ci --- types/enzyme/enzyme-tests.tsx | 22 ++++++++ types/enzyme/index.d.ts | 100 +++++++++++++++++++++++++++++----- 2 files changed, 107 insertions(+), 15 deletions(-) diff --git a/types/enzyme/enzyme-tests.tsx b/types/enzyme/enzyme-tests.tsx index d0a3eca97d..a576908ef3 100644 --- a/types/enzyme/enzyme-tests.tsx +++ b/types/enzyme/enzyme-tests.tsx @@ -40,6 +40,11 @@ interface MyRenderPropProps { children: (params: string) => ReactNode; } +interface MyProviderProps { + children: ReactElement | ReactElement[]; + value: string; +} + function toComponentType(Component: ComponentClass | StatelessComponent): ComponentClass | StatelessComponent { return Component; } @@ -529,6 +534,23 @@ function ShallowWrapperTest() { let shallowWrapper = new ShallowWrapper(
} />); shallowWrapper = shallowWrapper.renderProp('children')('test'); } + + function test_getWrappingComponent() { + const MyContext = React.createContext('test'); + function MyProvider(props: MyProviderProps) { + const { children, value } = props; + return ( + + {children} + + ); + } + const shallowWrapper = shallow(
} />, { + wrappingComponent: MyProvider, + }); + const provider = shallowWrapper.getWrappingComponent(); + provider.setProps({ value: 'test new' }); + } } // ReactWrapper diff --git a/types/enzyme/index.d.ts b/types/enzyme/index.d.ts index 3247ad84a7..66c353b5be 100644 --- a/types/enzyme/index.d.ts +++ b/types/enzyme/index.d.ts @@ -15,19 +15,23 @@ // TypeScript Version: 3.1 /// -import { ReactElement, Component, AllHTMLAttributes as ReactHTMLAttributes, SVGAttributes as ReactSVGAttributes } from "react"; +import { + ReactElement, + Component, + AllHTMLAttributes as ReactHTMLAttributes, + SVGAttributes as ReactSVGAttributes, +} from 'react'; export type HTMLAttributes = ReactHTMLAttributes<{}> & ReactSVGAttributes<{}>; -export class ElementClass extends Component { -} +export class ElementClass extends Component {} /* These are purposefully stripped down versions of React.ComponentClass and React.StatelessComponent. * The optional static properties on them break overload ordering for wrapper methods if they're not * all specified in the implementation. TS chooses the EnzymePropSelector overload and loses the generics */ export interface ComponentClass { - new(props: Props, context?: any): Component; + new (props: Props, context?: any): Component; } export type StatelessComponent = (props: Props, context?: any) => JSX.Element | null; @@ -379,7 +383,7 @@ export interface CommonWrapper

> { export type Parameters = T extends (...args: infer A) => any ? A : never; // tslint:disable-next-line no-empty-interface -export interface ShallowWrapper

extends CommonWrapper { } +export interface ShallowWrapper

extends CommonWrapper {} export class ShallowWrapper

{ constructor(nodes: JSX.Element[] | JSX.Element, root?: ShallowWrapper, options?: ShallowRendererProps); shallow(options?: ShallowRendererProps): ShallowWrapper; @@ -426,7 +430,9 @@ export class ShallowWrapper

{ * Shallow render the one non-DOM child of the current wrapper, and return a wrapper around the result. * NOTE: can only be called on wrapper of a single non-DOM component element node. */ - dive(options?: ShallowRendererProps): ShallowWrapper; + dive( + options?: ShallowRendererProps + ): ShallowWrapper; dive(options?: ShallowRendererProps): ShallowWrapper; dive(options?: ShallowRendererProps): ShallowWrapper; @@ -468,11 +474,20 @@ export class ShallowWrapper

{ /** * Returns a wrapper of the node rendered by the provided render prop. */ - renderProp(prop: PropName): (...params: Parameters) => ShallowWrapper; + renderProp( + prop: PropName + ): (...params: Parameters) => ShallowWrapper; + + /** + * If a wrappingComponent was passed in options, + * this methods returns a ShallowWrapper around the rendered wrappingComponent. + * This ShallowWrapper can be used to update the wrappingComponent's props and state + */ + getWrappingComponent: () => ShallowWrapper; } // tslint:disable-next-line no-empty-interface -export interface ReactWrapper

extends CommonWrapper { } +export interface ReactWrapper

extends CommonWrapper {} export class ReactWrapper

{ constructor(nodes: JSX.Element | JSX.Element[], root?: ReactWrapper, options?: MountRendererProps); @@ -572,8 +587,23 @@ export class ReactWrapper

{ parent(): ReactWrapper; } +export interface Lifecycles { + componentDidUpdate?: { + onSetState: boolean; + prevContext: boolean; + }; + getDerivedStateFromProps?: { hasShouldComponentUpdateBug: boolean } | boolean; + getChildContext?: { + calledByRenderer: boolean; + [key: string]: any; + }; + setState?: any; + // TODO Maybe some life cycle are missing + [lifecycleName: string]: any; +} + export interface ShallowRendererProps { - // See https://github.com/airbnb/enzyme/blob/enzyme@3.1.1/docs/api/shallow.md#arguments + // See https://github.com/airbnb/enzyme/blob/enzyme@3.10.0/docs/api/shallow.md#arguments /** * If set to true, componentDidMount is not called on the component, and componentDidUpdate is not called after * setProps and setContext. Default to false. @@ -586,7 +616,40 @@ export interface ShallowRendererProps { /** * Context to be passed into the component */ - context?: {}; + context?: any; + /** + * The legacy enableComponentDidUpdateOnSetState option should be matched by + * `lifecycles: { componentDidUpdate: { onSetState: true } }`, for compatibility + */ + enableComponentDidUpdateOnSetState?: boolean; + /** + * the legacy supportPrevContextArgumentOfComponentDidUpdate option should be matched by + * `lifecycles: { componentDidUpdate: { prevContext: true } }`, for compatibility + */ + supportPrevContextArgumentOfComponentDidUpdate?: boolean; + lifecycles?: Lifecycles; + /** + * A component that will render as a parent of the node. + * It can be used to provide context to the node, among other things. + * See https://airbnb.io/enzyme/docs/api/ShallowWrapper/getWrappingComponent.html + * Note: wrappingComponent must render its children. + */ + wrappingComponent?: ComponentType; + /** + * Initial props to pass to the wrappingComponent if it is specified. + */ + wrappingComponentProps?: any; + /** + * If set to true, when rendering Suspense enzyme will replace all the lazy components in children + * with fallback element prop. Otherwise it won't handle fallback of lazy component. + * Default to true. Note: not supported in React < 16.6. + */ + suspenseFallback?: boolean; + adapter?: EnzymeAdapter; + /* TODO what are these doing??? */ + attachTo?: any; + hydrateIn?: any; + PROVIDER_VALUES?: any; } export interface MountRendererProps { @@ -608,14 +671,20 @@ export interface MountRendererProps { * Shallow rendering is useful to constrain yourself to testing a component as a unit, and to ensure that * your tests aren't indirectly asserting on behavior of child components. */ -export function shallow(node: ReactElement

, options?: ShallowRendererProps): ShallowWrapper; +export function shallow( + node: ReactElement

, + options?: ShallowRendererProps +): ShallowWrapper; export function shallow

(node: ReactElement

, options?: ShallowRendererProps): ShallowWrapper; export function shallow(node: ReactElement

, options?: ShallowRendererProps): ShallowWrapper; /** * Mounts and renders a react component into the document and provides a testing wrapper around it. */ -export function mount(node: ReactElement

, options?: MountRendererProps): ReactWrapper; +export function mount( + node: ReactElement

, + options?: MountRendererProps +): ReactWrapper; export function mount

(node: ReactElement

, options?: MountRendererProps): ReactWrapper; export function mount(node: ReactElement

, options?: MountRendererProps): ReactWrapper; @@ -624,8 +693,9 @@ export function mount(node: ReactElement

, options?: MountRendererProps) */ export function render(node: ReactElement

, options?: any): Cheerio; -// See https://github.com/airbnb/enzyme/blob/v3.1.0/packages/enzyme/src/EnzymeAdapter.js +// See https://github.com/airbnb/enzyme/blob/v3.10.0/packages/enzyme/src/EnzymeAdapter.js export class EnzymeAdapter { + wrapWithWrappingComponent?: (node: ReactElement, options?: ShallowRendererProps) => any; } /** @@ -633,8 +703,8 @@ export class EnzymeAdapter { * This is enabling the Enzyme configuration with adapters in TS */ export function configure(options: { - adapter: EnzymeAdapter, - // See https://github.com/airbnb/enzyme/blob/enzyme@3.1.1/docs/guides/migration-from-2-to-3.md#lifecycle-methods + adapter: EnzymeAdapter; + // See https://github.com/airbnb/enzyme/blob/enzyme@3.10.0/docs/guides/migration-from-2-to-3.md#lifecycle-methods // Actually, `{adapter:} & Pick` is more precise. However, // in that case jsdoc won't be shown /**