I'm executing a basic React Jest test in a Button component and the test don't recognize an import.
Does anyone have any idea why the test fail in this import ?
Component:
import ...
import ... from 'styled-components';
import ... from 'styled-tools';
import {Icon} from 'xpto';
import {Default as theme} from 'Themes';
import * as mixins from '../../../config/styles/mixins';
...
&:hover{
background-color: #000;
border: 1px solid ${theme.colors.primary};
color: ${theme.colors.primary};
& svg:not([fill="none"]):not([fill="#000"]) {
fill: ${theme.colors.primary};
}
& .nohover svg {
fill: ${({color}) => color};
}
...
Error:
FAIL .../Button/index.test.js
● Test suite failed to run
Cannot find module 'Themes' from 'index.js'
5 |
6 | import {Icon} from 'xpto';
> 7 | import {Default as theme} from 'Themes';
| ^
8 |
9 | import * as mixins from '../../../config/styles/mixins';
10 |
at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:221:17)
at Object.<anonymous> (.../Button/index.js:7:1)
Jest test file:
import React from 'react';
import { mount } from 'enzyme';
import Button from './index';
describe('Button', () => {
it('should render correctly with no props', () => {
const component = mount(<Button/>);
expect(component).toMatchSnapshot();
});
});
Jest couldn't resolve your index.js in Themes folder. You can fix it by using one of two ways below:
Tell Jest how to resolve your file:
setting in package.json
"jest": {
"modulePaths": ["path to src folder which contains Themes folder"],
...
}
Check out this tutorial
Set NODE_PATH in .env file
NODE_PATH=src/ # src folder contains Themes folder
Related
I am creating some snapshot testing with jest. It gives me error with SwiperJs.
In my test i just want to have snapshot that renders component. I also have a single feature component which renders a feature comes from static data. Its test is passing without problem.
When i run test it gives me that eror.
SyntaxError: Unexpected token 'export'
> 2 | import { Swiper, SwiperSlide } from 'swiper/react';
Features.jsx
import { Link } from 'react-router-dom';
import { Swiper, SwiperSlide } from 'swiper/react';
import { Pagination } from 'swiper';
import featuresData from '../../data/featuresData';
import Feature from './Feature';
import illustration from '../../assets/features-illustration.svg';
import star from '../../assets/star.svg';
const Features = () => {
return (
////rest of the component
<Swiper
pagination={{
clickable: true,
}}
modules={[Pagination]}
>
///rest of the swiper
)
}
Features.test.jsx:
import renderer from 'react-test-renderer';
import Features from '../Features';
describe('Features', () => {
it('renders correctly', () => {
const tree = renderer.create(<Features />).toJSON();
expect(tree).toMatchSnapshot();
});
});
I installed jest packages with :
yarn add --dev jest babel-jest #babel/preset-env #babel/preset-react react-test-renderer
The solution for me was to introduce the following into my jest configuration file:
module.exports = {
// ...
transformIgnorePatterns: ['node_modules/(?!(swiper|ssr-window))']
}
Depending on your setup this may differ. In my case I'm extending a config provided by a framework, so all we needed was the above, however see here for a more detailed configuration.
I have the following issue when I tried to test a react components that implement the react-leaflet library
C:\digital-booking-ui\node_modules\react-leaflet\lib\index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export { useMap, useMapEvent, useMapEvents } from './hooks.js';
^^^^^^
SyntaxError: Unexpected token 'export'
1 | import React from "react";
2 | import { makeStyles } from "#material-ui/core";
> 3 | import { MapContainer, TileLayer, Marker, Popup, useMap } from "react-leaflet";
| ^
4 |
5 | const Map = () => {
6 | const classes = useStyles();
at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1728:14)
at Object.<anonymous> (src/components/accomodation/Map.js:3:1)
I search the problem on the internet and the recommendations I found don't work for me.
This error happen when I tried to render any component that has a relation with that library, for example, App.test.js
import { render, screen, prettyDOM } from '#testing-library/react';
import '#testing-library/jest-dom/extend-expect'
import App from './App';
import { BrowserRouter } from 'react-router-dom';
import { ThemeProvider } from '#material-ui/core';
import theme from "./theme";
let component = null;
beforeEach(() => {
component = render(
<BrowserRouter>
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
</BrowserRouter>
);
}
);
test('render App', () => {
expect(component).toBeTruthy();
});
How could I fix this? It seems a problem of Jest not recognizing the export of the components
In your package.json add these lines
"jest": {
"moduleNameMapper": {
"react-leaflet": "<rootDir>/mocks/reactLeafletMock.js"
}
}
Then in a "mocks" folder (or whatever you want) add a reactLeafletMock.js module that return an empty object
module.exports = {}
It should be ok (it worked for me)
You could eventually add "react-leaflet" hooks within the object to avoid other errors from Jest
module.exports = {
useMapEvents: () => {}
}
I'm trying to build a react component library that I can use in other applications and I'm running into an issue of packaging css/less with the component library.
in the component library package:
component.tsx
import React, { ReactElement } from 'react';
import styles from "./component.less";
const TestComponent: React.FC = (): ReactElement => {
....
return (
<div className={styles.root}>
....
</div>
);
};
export default TestComponent;
component.less
#bg-color: #428bca;
.root {
background-color: #bg-color;
}
I run the below commands to build the library:
> tsc --emitDeclarationOnly
> lessc src/component.less dist/library.css
> babel src --out-dir dist --extensions .ts,.tsx --source-maps
> copyfiles -u 1 src/**/*.less dist/
and in the dist directory get this:
> index.d.ts
> index.js
> library.css
> component.less
> ....
in a different application I just install the library and use the component:
import TestComponent from "library-package";
<TestComponent /> // in the render somewhere
and when I start this application the component is rendered but the css/less code is not applied and not imported.
I'd like to include some default css inside of the library package. And I know that I could just include the library.css in the index.tsx of an application and the css could work, but I don't want the other application to have to include a css file or have a less loader to handle the css if it doesn't use less itself.
I assume that the problem currently is that the application doesn't know how to handle .less files from the library because it doesn't have a less loader setup (although I don't get an error about anything)
tldr: an application would just install the component library, include the component in a render and the component will render with some css (preferrably using less in the library). Is that possible to do?
I guess I was looking for something like the styled-components but using less + minifying instead of writing the CSS in a JavaScript file and wrapping HTML tags.
With the styled-components library I got it to work this way:
component.tsx
import React, { ReactElement } from "react";
import cssesc from "cssesc";
import styled, { ThemeProvider, DefaultTheme } from "styled-components";
export interface TestComponentTheme extends DefaultTheme {
backgroundColor?: string;
}
const DEFAULT_THEME: TestComponentTheme = {
backgroundColor: "#428bca",
};
const StyledDiv = styled.div`
background-color: ${props => cssesc(props.theme.backgroundColor)};
`;
interface TestComponentInput {
theme?: TestComponentTheme;
}
const TestComponent: React.FC<TestComponentInput> = ({theme}: TestComponentInput ): ReactElement => {
....
let componentTheme: TestComponentTheme = Object.assign({}, DEFAULT_THEME);
if (theme) {
componentTheme= Object.assign({}, componentTheme, theme);
}
return (
<ThemeProvider theme={componentTheme}>
<StyledDiv>
....
</StyledDiv>
</ThemeProvider>
);
};
export default TestComponent;
building the library requires just two steps now:
> tsc --emitDeclarationOnly
> babel src --out-dir dist --extensions .ts,.tsx --source-maps
and there are no CSS files in the dist directory anymore:
> index.d.ts
> index.js
> ....
in a different application I just install the library and use the component (which renders with the CSS inline):
import TestComponent from "library-package";
<TestComponent /> // in the render somewhere
and optionally I can overwrite the CSS of the component:
import TestComponent, { TestComponentTheme } from "library-package";
const customTheme: TestComponentTheme = {
backgroundColor: "#000fff",
};
<TestComponent theme={customTheme} /> // in the render somewhere
I'm trying to use jest-dom to test a component's styles, and I'm having the error:
"TypeError: expect(...).toHaveStyle is not a function"
My component is a simple link with styled-components:
import styled from 'styled-components'
export const Link = styled.a`
color: #fff;
`
In my test I'm doing:
describe('Link', () => {
it('should display color on the link', () => {
render(<Link href="/x">Test</Link>)
}
expect(screen.getByRole('link', { name: /test/i })).toHaveStyle({ color: '#fff' })
}
I created a settings file (jest.config.js) with:
module.exports = {
setupFilesAfterEnv: ['<rootDir>/.jest/setup.js'],
}
At the root of the project I created the .jest / setup.js file and imported the js-dom:
import '#testing-library/jest-dom'
From https://testing-library.com/docs/svelte-testing-library/setup/
6.2 Add the following to your Jest configuration in package.json
{
"setupFilesAfterEnv": ["#testing-library/jest-dom/extend-expect"]
}
You could add it to your jest.config.js since you already have that, rather than package.json.
Since #testing-library/dom v5.0.0, there are some breaking changes compare/v4.2.4...v5.0.0
Before v5.0.0, you should use import '#testing-library/jest-dom/extend-expect';
Since v5.0.0, you should use import '#testing-library/jest-dom';
You didn't add the matchers for expect correctly. That's the reason you get the error.
you can try this :
import { toHaveStyle } from '#testing-library/jest-dom'
expect.extend({ toHaveStyle })
it works for me.
Use the following versions in your package:
"dependencies": {
"#types/styled-components": "5.9.1",
"styled-components": "^5.2.0"
},
and import this package into your test file:
import '#testing-library/jest-dom/extend-expect'
I found the answer from this link
To be short:
Run: npm install --save-dev #testing-library/jest-native
Add: import '#testing-library/jest-native/extend-expect' to your test file
Add: import { toHaveStyle } from '#testing-library/jest-native/dist/to-have-style'
Add: expect.extend({toHaveStyle})
Finally, you have the toHaveStyle for your expect
Sample code:
/**
* #format
*/
import 'react-native';
import '#testing-library/jest-native/extend-expect';
import React from 'react';
import App from '../App';
import {render, screen} from '#testing-library/react-native';
import { toHaveStyle } from '#testing-library/jest-native/dist/to-have-style';
expect.extend({toHaveStyle})
it('renders correctly', () => {
render(<App/>);
const text = screen.getByTestId('Sample Text')
expect(text).not.toBeNull();
const button = screen.getByTestId('Sample Button')
expect(button).not.toBeNull();
expect(button).toHaveStyle({
backgroundColor: 'transparent'
})
});
install jest-styled-components
npm i -D install jest-styled-components
then use .toHaveStyleRule
Example:
import React from 'react';
import { render } from 'react-testing-library';
import Button from '../Button';
import 'jest-styled-components';
describe('<Button />', () => {
it('should render text', () => {
const { getByText } = render(<Button text="Button" />);
expect(getByText('Button')).not.toBeNull();
});
it('should have correct style with background color', () => {
const { getByText } = render(<Button text="Button" color="#fff" />);
expect(getByText('Button')).toHaveStyleRule('background', '#fff');
});
});
I added to my gatsby's webpack config directory-named-webpack-plugin which makes it possible to import files that have the same name as its parent direcory. For example I can use path 'components/Link' instead of 'components/Link/Link':
const DirectoryNamedWebpackPlugin = require('directory-named-webpack-plugin');
exports.onCreateWebpackConfig = ({ actions }) => {
actions.setWebpackConfig({
resolve: {
plugins: [new DirectoryNamedWebpackPlugin()],
},
});
};
But unfortunately when I run my test using jest I get an error like that (I also use absolute imports):
FAIL src/components/atoms/Link/Link.test.js
● Test suite failed to run
Cannot find module 'components/atoms/Icon' from 'src/components/atoms/Link/Link.js'
Require stack:
src/components/atoms/Link/Link.js
src/components/atoms/Link/Link.test.js
3 | import { useAnimation } from 'framer-motion';
4 | import PropTypes from 'prop-types';
> 5 | import Icon from 'components/atoms/Icon';
| ^
6 | import arrow from 'assets/svgs/icon_arrow.svg';
7 | import S from './Link.styles';
8 | import animations from './Link.animations';
at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:307:11)
at Object.<anonymous> (src/components/atoms/Link/Link.js:5:1)
Here is my folder structure:
Is there any solution to this? I'm pretty new in the jest configuration.
Use index.js in each folders like this and forget DirectoryNamedWebpackPlugin at all
import Link from './Link';
export default Link;