How to test react component using jest? - javascript

I am getting SyntaxError: /test/ut/client/breadcrumbs/BreadCrumbs.ut.test.js: Unexpected token (12:6) error. Code is given below. And the code coverage is 0% because test suits failed.
I am using jest v-"^24.8.0", jest-dom v-"^3.5.0", jest-junit v-"^6.4.0"
describe("BreadCrumbs", () => {
afterEach(cleanup);
test("Should render breadcrumbs on usecase page", () => {
const useCaseBreadCrumbs = create(
<BreadCrumbs
list={USECASE_BREADCRUMBS.list}
disabledLabel={USECASE_BREADCRUMBS.disabledLink}
/>
);
console.log(useCaseBreadCrumbs);
expect(tree).toMatchSnapshot();
});
});

You need to add import React from "react"; on top

Related

Is there a way to import a function using Next.js dynamic import? react-component-export-image issues with Next.js ssr

I was getting the 'window is not defined' error when importing react-component-export-image so I used a dynamic import to get around that. I don't get that error anymore but now I get 'exportComponentAsPNG(componentRef) is not a function'. Is there a better way to deal with the 'window is not defined' error or a way to use the function I am importing dynamically? If not, is there a different npm library that works to generate an image from a react component?
import React, { useRef } from 'react'
// import { exportComponentAsPNG } from 'react-component-export-image' *This gave window not defined error so I used dynamic import*
import dynamic from 'next/dynamic'
import ProductCard from '../ProductCard/ProductCard.component'
import Button from '../Button/Button.component'
const { exportComponentAsPNG } = dynamic(
() => import('react-component-export-image'),
{
ssr: false
}
)
const Plaque = () => {
const componentRef = useRef()
// eslint-disable-next-line react/display-name
const ComponentToPrint = React.forwardRef((props, ref) => {
return (
<div ref={ref}>
<ProductCard />
</div>
)
})
return (
<ComponentToPrint ref={componentRef} />
<button onClick={() => exportComponentAsPNG(componentRef)}> // "Error: exportComponentAsPNG is not a function"
Export As PNG
</button>
)
}
export default Plaque
next/dynamic is used to dynamically import React components, not regular JavaScript functions or libraries.
For that, you can use a regular dynamic import on exportComponentAsPNG inside the onClick callback.
<button onClick={async () => {
const { exportComponentAsPNG } = await import('react-component-export-image')
exportComponentAsPNG(componentRef)
}}>
The exportComponentAsPNG function needs access to window which is undefined with server side rendering. I was able to fix the issue by dynamically importing the Plaque component that used exportComponentAsPNG to the page where it is called with sever side rendering set to 'false'.
import dynamic from 'next/dynamic'
const Plaque = dynamic(() => import('../compnonents/Plaque'), {
ssr: false
})
const Page = () => {
return <Plaque />
}
export default Page
Now that the component is no longer using SSR I was able to import and use the function normally.
import { exportComponentAsPNG } from 'react-component-export-image'
Here you can find the documentation for the library: https://www.npmjs.com/package/react-component-export-image

Element type is invalid. Expected a string, found undefined

This one occurred just after a next-auth update. Suddenly it throws this error:
Error: Element 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.
Check the render method of `MyApp`.
So I checked the MyApp file, but there doesn't seem to be anything wrong about it, nothing that I have seen at least.
_app.tsx (_app file in next.js)
import React from "react";
import { start, done } from "nprogress";
import "nprogress/nprogress.css";
import router from "next/router";
import "./styles/patch.css";
import { Provider } from "next-auth/client";
import { ApolloProvider } from "#apollo/client";
import { useApollo } from "../apollo/apolloClient";
router.events.on("routeChangeStart", () => start());
router.events.on("routeChangeComplete", () => done());
router.events.on("routeChangeError", () => done());
const MyApp = ({ Component, pageProps }) => {
const apolloClient = useApollo(pageProps.initialApolloState);
React.useEffect(() => {
// Remove the server-side injected CSS.
const jssStyles = document.querySelector("#jss-server-side");
if (jssStyles) {
jssStyles.parentElement.removeChild(jssStyles);
}
}, []);
return (
<ApolloProvider client={apolloClient}>
<Provider session={pageProps.session}>
<Component {...pageProps} />
</Provider>
</ApolloProvider>
);
};
export default MyApp;
Did I miss something that could've caused this error?
EDIT:
Apparently, it was fine when I used webpack 4. It threw this error upon using webpack 5. But it would be good if there was a solution for webpack 5.
EDIT 2:
When I updated next to version 10.2, it worked perfectly fine. I must've been hasty on things perhaps so I guess there wasn't any problem in the first place. Other than that, I appreciate the answers that had been put in here.
do not use query like this :
React.useEffect(() => {
// this is wrong !!!
const jssStyles = document.querySelector("#jss-server-side");
if (jssStyles) {
jssStyles.parentElement.removeChild(jssStyles);
}
}, [])
try using useRef hook instead ex:
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
// `current` points to the mounted text input element
inputEl.current.focus();
};
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}

React test fails with react-hook-media-query

I'm using react-hook-media-query in my project but the test is failing because of it.
This is the code:
import React from 'react';
import useMediaQuery from 'react-hook-media-query';
const MyCompp = (props) => {
const minWidth1200 = useMediaQuery('(min-width: 1200px)');
...
}
test file:
import React from 'react';
import App from './App';
import { render } from '#testing-library/react';
import { WrapIntlProvider, WrapStore } from '../testsHelper';
jest.mock('react-redux', () => ({
...jest.requireActual('react-redux'),
useSelector: () => ({
locale: 'en-US',
messages: {}
})
}));
describe('<App />', function () {
it('should render <App />', () => {
const { container } = render(
<WrapStore>
<WrapIntlProvider>
<App />
</WrapIntlProvider>
</WrapStore>
);
expect(container).toMatchSnapshot();
});
});
and when I run the tests it throws this error message:
● Test suite failed to run
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:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.
• 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:
/.../node_modules/react-hook-media-query/dist/index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import
{ useState, useEffect } from 'react';
^^^^^^
SyntaxError: Cannot use import statement outside a module
> 2 | import useMediaQuery from 'react-hook-media-query';
| ^
Any ideas how to get rid of it?

Error when run the test "Cannot find module "

I am new to writing Unit tests and i am trying to write unit tests to my react application using testing-library/react and jest
Here is the test code "Home.test.js"
import React from 'react';
import {render, cleanup} from '#testing-library/react';
import '#testing-library/jest-dom/extend-expect';
import Home from "../src/Home";
afterEach(cleanup);
describe("Tests for HomePage", function() {
it("should render without throwing an error", function() {
const { homePage } = render(<Home />);
//check something here
});
});
Here is my code in component "Home.js"
import * as React from "react";
import { Panel, Shell, Button } from "#myorg/core";
import { home_icon, new_icon } from "#myorg/icons";
function Home(props) {
const openDialog = React.useCallback(() => {
//do something
});
return (
<Shell.Page breadcrumbs={[t("demo:Home")]}>
<Panel style={{ height: "100%" }}>
<h2>App Header</h2>
<Button onClick={openDialog} variant="primary">
<img src={new_icon} width="20" />
{t("demo:New Asset")}
</Button>
</Panel>
</Shell.Page>
);
}
error I get when I run "npm run test"
Cannot find module '#myorg/icons' from 'Home.js'
I believe you are trying to use the tsconfig.json options paths, which will be ignored by jest (or by other testing frameworks). You need to manually replicate all your paths definition in jest.config.js and manually keep them updated using the jest config option moduleNameMapper like this:
moduleNameMapper: {
// translate all your custom paths here, read the doc in the link above
'^#finder/(.*)$': '<rootDir>/files-manipulation/$1',
'^#metadata/(.*)$': '<rootDir>/folder-metadata/$1',
'^#logger/(.*)$': '<rootDir>/logging/$1',
// ...and so on
},

React Native jest test: TypeError: Cannot read property 'unsubscribeFromTopic' of undefined

I'm using react-native-fcm and jest to test my React Native app. I have a pretty basic test, it looks like this:
import 'react-native';
import React from 'react';
import PushController from '../app/PushController';
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
it('works correctly', () => {
const tree = renderer.create(
<PushController />
);
});
And PushController is somewhat large, so here's the interesting parts
import React, { Component } from 'react';
import { AsyncStorage } from 'react-native';
import FCM from 'react-native-fcm';
export default class PushController extends Component {
(...)
componentDidMount() {
if (this.notificationListener) this.notificationListener.remove();
this.notificationListener = FCM.on('notification', (notif) => {
if (!notif.local_notification) {
this.notifyUser(notif.coffee);
}
});
FCM.unsubscribeFromTopic('/topics/coffee');
FCM.subscribeToTopic('/topics/coffee');
}
(...)
However, when running the test I get
__tests__/PushControllerTest.js
● works correctly
TypeError: Cannot read property 'unsubscribeFromTopic' of undefined
at Object.FCM.unsubscribeFromTopic (node_modules/react-native-fcm/index.js:86:15)
at PushController.componentDidMount (app/PushController.js:44:26)
at node_modules/react-test-renderer/lib/ReactCompositeComponent.js:265:25
at measureLifeCyclePerf (node_modules/react-test-renderer/lib/ReactCompositeComponent.js:75:12)
at node_modules/react-test-renderer/lib/ReactCompositeComponent.js:264:11
at CallbackQueue.notifyAll (node_modules/react-test-renderer/lib/CallbackQueue.js:76:22)
at ReactTestReconcileTransaction.ON_DOM_READY_QUEUEING.close (node_modules/react-test-renderer/lib/ReactTestReconcileTransaction.js:36:26)
at ReactTestReconcileTransaction.TransactionImpl.closeAll (node_modules/react-test-renderer/lib/Transaction.js:206:25)
at ReactTestReconcileTransaction.TransactionImpl.perform (node_modules/react-test-renderer/lib/Transaction.js:153:16)
at batchedMountComponentIntoNode (node_modules/react-test-renderer/lib/ReactTestMount.js:69:27)
I've tried including lots of stuff in the test, like jest.mock('react-native-fcm') and others, but I can't get it to work at all. I get that jest automatically mocks the library, but I don't understand why FCM is undefined. Any ideas?
I managed to solve it, finally! Simply needed to change my test to
import 'react-native';
import React from 'react';
import PushController from '../app/PushController';
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
import FCM from 'react-native-fcm'; // <-- This
it('works correctly', () => {
FCM.unsubscribeFromTopic = jest.fn(); // <-- These two
FCM.subscribeToTopic = jest.fn();
const tree = renderer.create(
<PushController />
);
});
To make sure the actual calls are mocked. I did a lot of googling before this, so I'm sure this will be useful for someone.

Categories

Resources