React Unit Testing with Framework7 Components? Is it possible?

How do I configure Jest so I can properly unit test my components which utilize F7 components?

Anytime I try to mount a React function component which has child F7 components in it (being rendered/returned), Jest gives me this error:

 console.error node_modules/react/cjs/react.development.js:315
      Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Do I need to port my react code over to typescript? What can be done?

@andrewjamesbibby @Suthern - tagging you folks since you struggled with similar issues above :slight_smile:

Looks like it might be related to this bug?

HI @Alex_Houchens i just stubbed the framework7 components and was doing it in vue… so i did not see this particular error. But looks like its react related?

Issue seems on CRA/Jest side, i couldn’t figure out how to make Jest to properly compile exports in source code.

Best i could get is to import components directly.
Try instead of this:

import { App, View } from 'framework7-react' 

to use

import App from 'framework7-react/components/app' ;
import View from 'framework7-react/components/view' ;

Hi @nolimits4web, thanks for helping to take a look!

Would it be possible for you to also share your babel.config.js and jest.config.js for your Jest setup? I did as you were saying but now Jest is complaining with:

    Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

    Here's what you can do:
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/en/configuration.html

    Details:

    C:\Users\webte\Desktop\grevera\orchid-airship\ui\node_modules\framework7-react\components\block-title.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import React from 'react';
                                                                                             ^^^^^^

    SyntaxError: Cannot use import statement outside a module
    >  9 | import BlockTitle from 'framework7-react/components/block-title';

Hi @andrewjamesbibby - I was considering the stubbing approach as well… however I did have a question about that particular approach. How did you write meaningful tests or assertions (like interacting with forms) for example if you had to stub out all of the F7 components?

It also looks like it might be related to some in flight changes on the Jest side, which they are seeking to resolve here (with Jest 26 as mentioned in this comment):

A lot of what I was doing I needed to check that data was show correctly so by stubbing out certain f7 components for example <f7-list-item> <f7-page> etc etc I could still assert it was true. There would be no need to test that f7 works, as it works as intended.

Also I had extracted quite a lot of method into vuex anyway so I could test most of the methods independently. I would like to have been able to test things likes what was shown in a virtual list but struggled to import and use f7 components into mounted test components.

I was using things like this.$f7.dialog and this.$f7.ptr.done() within methods and I was able to easily mock these and just test whether they has been fired where they should have done in the various components methods.

As for interacting with forms I could see how that could be tricky if you are using the f7 forms components directly. But perhaps you can just mock them out, then test all of the methods which handle the form by mocking the data passed to your submit function and asserting it is behaving as you expect?

Found a workaround until Jest 26

Using that workaround coupled with the alternative import @nolimits4web does seem to partially work for some components, (e.g. BlockTitle)

In my case I also had to remove node_modules from being ignored in transformIgnorePatterns in the jest.config.js

transformIgnorePatterns: [
    "\\\\node_modules\\\\" <--- delete
  ],

However, it doesn’t work for all components, as now I am seeing this issue when running the Jest test runner and trying to import the F7 Page component:

console.error
      Error: Uncaught [TypeError: self.$f7ready is not a function]

With React, unfortunately, it relies heavily on unit testing components being rendered. Which I’m not personally a huge fan of - for reasons like this, even when a lot of the code that could be functionally tested (such as custom Hooks) can’t be tested independently of being rendered in a component context.

Personally, I would prefer to do as you’re suggesting. Just unit test methods and functions independent of component context, but that’s not really recommended or possible in React. :frowning:

I am seeing this same problem with $f7ready. This thread is pretty much the only Google result for the problem so I was curious if you had found any solution to it?