ionic-team / stencil-redux

MIT License
97 stars 20 forks source link

Injecting the store for unit-tests: 'store' is undefined #6

Open DorianGrey opened 6 years ago

DorianGrey commented 6 years ago

Hi there,

I've recently played a bit with stenciljs and tried to integrate redux using this connector. While everything works (approx.) fine for development und production build, I've faced some problems when trying to unit test components that have the Store as a Prop trying to connect to it.

A simple example is the my-app component, which attempts to set up the store: https://github.com/DorianGrey/stencil-playground/blob/master/src/components/my-app/my-app.tsx

When executing the unit test (see https://github.com/DorianGrey/stencil-playground/blob/master/src/components/my-app/my-app.spec.ts) for it, this raises an error like this:

 FAIL  src/components/my-app/my-app.spec.ts
  ● Console

    console.error node_modules/@stencil/core/dist/testing/index.js:7268
      Error: Cannot read property 'setStore' of undefined
      TypeError: Cannot read property 'setStore' of undefined
          at MyApp.Object.<anonymous>.MyApp.componentWillLoad (/home/linne/Projects/stencil-playground/src/components/my-app/my-app.tsx:14:20)
          at update (/home/linne/Projects/stencil-playground/node_modules/@stencil/core/dist/testing/index.js:896:48)
          at plt.queue.tick (/home/linne/Projects/stencil-playground/node_modules/@stencil/core/dist/testing/index.js:854:34)
          at flush (/home/linne/Projects/stencil-playground/node_modules/@stencil/core/dist/testing/index.js:445:33)
          at _combinedTickCallback (internal/process/next_tick.js:131:7)
          at process._tickCallback (internal/process/next_tick.js:180:9)
          at TestWindow.<anonymous> (/home/linne/Projects/stencil-playground/node_modules/@stencil/core/dist/testing/index.js:9525:27)
          at Generator.next (<anonymous>)
          at fulfilled (/home/linne/Projects/stencil-playground/node_modules/@stencil/core/dist/testing/index.js:9461:58)
          at <anonymous>
          at process._tickCallback (internal/process/next_tick.js:188:7)

This is obviously raised from the componentWillLoad look that attempts to configure the store. I'm not sure why this happens, since everything works fine in the other modes. I might need to somehow inject the store as a property in another way, but I did not find any clue how, especially since this needs to happen before componentWillLoad is called.

The repo can be found here: https://github.com/DorianGrey/stencil-playground

Steps to reproduce

Further notes

mlynch commented 6 years ago

Might be a stencil issue, not sure. Leaving open as I don't have a solution but would like others to chim in

boradakash commented 5 years ago

Any updates? I'm also facing the same issue for the latest version.

 "@stencil/core": "^1.1.2",
 "@stencil/redux": "^0.1.1",
 "@stencil/router": "^1.0.1",
luciomartinez commented 5 years ago

This worked for me:

add import '@stencil/redux'; to your root app.tsx file.

PR to add into the docs: https://github.com/ionic-team/stencil-redux/pull/45

joewoodhouse commented 5 years ago

@DorianGrey Anyone found a solution to this? @mlynch I'm still not really sure the official replacement for @Prop({ context: 'store' }) store: Store; has been published in the Stencil docs? That might at least provide a starting point for finding a solution?

RathiRohit commented 5 years ago

@DorianGrey @joewoodhouse @mlynch @boradakash After facing this store mocking issue for past few days finally found something to inject mock store into components during unit tests. With the new Stencil testing utility newSpecPage() (instead of using old TestWindow()) you can pass an optional, undocumented (and deprecated) argument "context" with mock store in it. This way the component receives the mock store before componentWillLoad is executed.

    const page = await newSpecPage({
            components: [MyApp],
            html: "<my-app></my-app>",
            context: {
                    store: mockStore,
            },
    });
    await page.waitForChanges();
    page.flushQueue();