jest-styled-components icon indicating copy to clipboard operation
jest-styled-components copied to clipboard

Property 'getChildContext' does not exist on type 'Component<{}, {}, any>' (TypeScript)

Open drwpow opened this issue 6 years ago • 11 comments

Using the functions from the theming section of the README in TypeScript, and getting the following error:

export const shallowWithTheme = (tree: React.ReactElement<{}>) => {
  const context = shallow(<ThemeProvider theme={theme} />)
    .instance()
    .getChildContext();
     ^^^^^^^^^^^^^^^
  return shallow(tree, { context });
};

error TS2339: Property 'getChildContext' does not exist on type 'Component<{}, {}, any>'.

This has something to do with enzyme’s instance() returning a generic React component that doesn’t seem to have a getChildContext method.

Has anyone else encountered this issue, and know of a workaround? Thanks!

drwpow avatar Dec 06 '18 02:12 drwpow

If I understood right, getChildContext does not exist anymore, as styled-components 4 is using the React 16 Context API. Even when "dumb casting" the returned component to any and calling getChildContext, you'll get a runtime error telling you that getChildContext is not a function.

niklaskorz avatar Dec 09 '18 18:12 niklaskorz

My workaround for now is:

import * as React from 'react';
import { mount, render, shallow } from 'enzyme';
import { ThemeProvider } from 'styled-components';
import * as theme from './theme';

export const mountWithTheme = (children: any) =>
  mount(<ThemeProvider theme={theme}>{children}</ThemeProvider>);

export const renderWithTheme = (children: any) =>
  render(<ThemeProvider theme={theme}>{children}</ThemeProvider>);

export const shallowWithTheme = (children: any) =>
  shallow(<ThemeProvider theme={theme}>{children}</ThemeProvider>);

It’s pretty dumb, but works for the most part. Haven’t used it much yet to see if it’s missing out on anything by not passing context directly to enzyme.

drwpow avatar Dec 12 '18 17:12 drwpow

Any other solution for this issue.

We have hundred of thousands components and now we got stuck to upgrade.

aminpaks avatar Jan 03 '19 15:01 aminpaks

@dangodev mounting with the whole provider is not really helpful, as it spits out the whole theme object in my snapshots, and the styled parts still have a lambda function reference wherever I use the theme:

Theme provider with theme object in snapshot:

<ThemeProvider theme={
        Object {
          "colors": Object {
          ...
          ...

And styled components with theme-computed props:

border-radius: ",[Function],"px;

That's the reason why in the examples of jest-styled-components they want to setup the context and use that for the mount of your actual component.

justusromijn avatar Apr 09 '19 07:04 justusromijn

That’s probably true @justusromijn because I don’t really use snapshots! 😅 They sound great in theory but in practice for us they turned out to be pure noise. In our tests we’ll specifically target the elements/styles/properties/text/etc. that should display in a scenario rather than play “spot the differences.” So I didn’t really notice that method not working for snaps.

Either way, it’s still an issue with the types for this library.

drwpow avatar Apr 09 '19 13:04 drwpow

@dangodev I think when I switch to react hooks, I can get my snapshots to be better as well, since the React Tree becomes a lot more flat without all those wrapping HoC's or providers in a lot of cases.

Snapshot testing I only use more for regression, so I just add them in as an addition to specific functionalities that I test. Just a safety net :)

justusromijn avatar Apr 12 '19 08:04 justusromijn

Maybe we could somehow swap the ThemeContext that is used by styled components, by defining our own ThemeContext that has a default value defined by us on test setup?

Then we wouldn't have to mount it with theme provider at all? (Am I right?)

jtomaszewski avatar Apr 18 '19 12:04 jtomaszewski

Enzyme 3.10.0 adds a new API that makes it easy to wrap shallow() and mount() with context. It works perfectly with snapshots as far as I can tell.

Here's my Typescript code for a mount wrapper:

const mountWithTheme = (tree: ReactElement<any>, theme: DefaultTheme) => {
    const WrappingThemeProvider: React.FC<{children: React.ReactChild}> =
        (props) => (
            <ThemeProvider theme={theme}>
                {props.children}
            </ThemeProvider>
        );

    return mount(
        tree,
        {wrappingComponent: WrappingThemeProvider} as MountRendererProps //Override typing because @types/enzyme doesn't have wrappingComponent yet https://github.com/DefinitelyTyped/DefinitelyTyped/pull/36667
    );
};

I've opened a documentation fix request for jest-styled-components here: #256

JustinLex avatar Jul 08 '19 13:07 JustinLex

Enzyme 3.10.0 adds a new API that makes it easy to wrap shallow() and mount() with context. It works perfectly with snapshots as far as I can tell.

Here's my Typescript code for a mount wrapper:

const mountWithTheme = (tree: ReactElement<any>, theme: DefaultTheme) => {
    const WrappingThemeProvider: React.FC<{children: React.ReactChild}> =
        (props) => (
            <ThemeProvider theme={theme}>
                {props.children}
            </ThemeProvider>
        );

    return mount(
        tree,
        {wrappingComponent: WrappingThemeProvider} as MountRendererProps //Override typing because @types/enzyme doesn't have wrappingComponent yet https://github.com/DefinitelyTyped/DefinitelyTyped/pull/36667
    );
};

I've opened a documentation fix request for jest-styled-components here: #256

Works perfect for shallow rendering. However its doesn't work when I try the same solution for mounting. It seems like the theme prop is undefined. I have found many related open and closed issues, but none of these have a proper solution or workaround.

Can someone help me pls?

silltho avatar Aug 05 '19 13:08 silltho

any updates or fixes? maybe it have sense to update README ?

ps: i'm using this workaround:

export const mountWithTheme = (children, theme = DefaultTheme) => {
  ThemeConsumer._currentValue = theme
  return mount(children)
}

kerosan avatar Jul 13 '20 11:07 kerosan

I'm using this documentation and this is the reason why raise my hands and say: "I have the same problem."

BirgitPohl avatar Oct 23 '20 07:10 BirgitPohl