How to test the style inside the CSS class for React component using Jest and Enzyme? - reactjs

Consider in CSS,
.content
{
width:500px;
box-sizing: border-box;
}
I have added this css class inside react component as following
const Banner = () => {
return (<div className="content">This is message content</div>);
}
How to write jest and enzyme test cases to ensure the 'box-sizing' with 'border-box' applied properly?
Notes: I can write the test case to ensure the ".content" class added to this element. But exactly, i need to write test case to ensure the value in 'box-sizing'.

I am not sure how to fix your issue, but keep in mind your test will not cover
* {
box-sizing: border-box;
}
if you will defined somewhere alse.
From my perspective, it does not make sense to test styles, because we can not guaranty from the test perspective that element will look like we want to. So still you will need to open the browser and check your element works properly, but you are writing tests to avoid it.

By adding this code to Banner.test.js file, it'll check if className called content have inline style property for box-sizing and is it equal to border-box or not. But it'll test only inline styles.
const banner = shallow(<Banner/>);
it("render propperely", () => {
expect(banner).toMatchSnapshot();
expect(banner.find(".content")
.get(0).props.style).toHaveProperty("box-sizing", "border-box");
});

Related

How to ignore style changes in styled-components during snapshot tests in jest

Assume i have a simple component I wish to snapshot test:
const Component = styled.div`{
color: red;
}`
My snapshot test wishes to ensure that the div renders, but the styling is not important. So if I did a snapshot test on this Component, and i changed color from red to blue, and a new classname is generated, it would not fail the snapshot test.
In short, is there any way I can either ignore className in snapshot tests, or tell styled-components to generate static class names to be deterministic in tests?
I think what you are looking for is the jest-styled-components package which does exactly this.
For an example like yours, this would result in a snapshot like this:
exports[`it works 1`] = `
.c0 {
color: red;
}
<div
className="c0"
/>
`;
where c0 is always stable.

how to import css file in react when generating static html and inject imported css into html head tag?

I am trying to generate static html from react using renderToStaticMarkup method. The problem I am facing right now is that I am not able to import css into react component. I want to import css in my React components like css-modules (import styles from './style.css'). And then inject that loaded css into generated static html head. How can I accomplish that?
P.S. I can't use webpack due to some constraints. If there is any babel plugin availabe for this specific case, then please let me know.
Here is how I am generating static html from react component:
const reactElement = require('react').createElement;
const ReactDomServer = require('react-dom/server');
const renderHTML = Component => {
return ReactDomServer.renderToString(reactElement(Component))
}
You can pass a URL in as a prop and render a <link/> tag. Made an example here, not sure if that would meet your needs or if you need it to be a style tag.
This may be challenging without a lot of custom logic.
If you want to inline the CSS only for the initial render and then fetch the rest after the initial render, styled-components may be a better option because it supports exactly what you're trying to achieve without too much configuration: https://www.styled-components.com/docs/advanced#server-side-rendering
May be I am too late you can also create It like this way.
React.createElement("style", {},[ "body {background-color: powderblue;}
h1 {color: blue;}
p {color: red;}" ])
Output:
<style>
body {background-color: powderblue;}
h1 {color: blue;}
p {color: red;}
</style>
Since createElement take 3 params and last one is children we can put our vanila css inside it as a children. You can put any imported file in the form of string and it will convert to style tag

How to get CSS Modules to work with Reactstrap cssModule propType?

I noticed most form elements in the Reactstrap documentation have a PropType of a cssModule. I would assume that means I could override the default Reactstrap styles and do something like this:
Formtext.module.css
.formtext {
background-color: blue;
border: 2px solid black;
margin: 10px;
}
SimpleForm.jsx
import styles from "./Formtext.module.css";
...
<FormText cssModule={styles.formtext}>
This is some placeholder help text...
</FormText>
```
However, this doesn't seem to work. Checking my react dev tools the cssModule prop evaluates to undefined.
I'm using Using Reactstrap 5.0 and create-react-app 1.1.5
Is there something I'm unaware of that I need to do?
Do I need to eject to be able to use css-modules?
Can someone point me to an example of how to use the Reactstrap's cssModule prop correctly?
For reference here is the proptypes definition from Reactstrap docs
FormText.propTypes = {
children: PropTypes.node,
inline: PropTypes.bool,
tag: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), // default: 'small'
color: PropTypes.string, // default: 'muted'
className: PropTypes.string,
cssModule: PropTypes.object,
};
On cssModule
It looks like cssModules doesn't behave quite like you would think; the prop doesn't take a single, overriding class - it takes a rejected class and a replacement class.
Reactstrap uses mapToCssModules to get this done. See its documentation here. Take note of the usage example:
<Example tag="div" cssModule={{ 'w-100': 'w-75' }} />
So your case would look something like this:
<FormText cssModule={{ 'form-text' : styles.formtext }} />
This will completely surpress the 'form-text' class though (which in your case, only contributes display: block. If you'd like to override more selectively, see below.
Try this instead
In the FormText source code, it looks like you may be able to do your overrides in a different way:
If you want to omit the form-text class altogether, include inline as a prop,
If you want to omit any color-related bootstrap classes, set 'color' to false (or something falsy),
set the className prop to your CSS Module object (styles.formtext).
<FormText className={styles.formText} color='' inline>
Test formtext
</FormText>
The most important part here is actually the className prop. You can also further override styling by including a tag prop (again, check the FormText docs).
Hope this was helpful! Happy holidays! 🦃🎅
I did not really get the accepted answer, but I had the same problem recently and in my opinion, cssModule behaves exactly as one would expect.
You just pass an imported module object and then specify classes they will be referenced towards the module.
Here is my example (from create-react-app) how I did fix Navbar to get it's bootstrap styles from my bootstrap module (as I don't import bootstrap globally):
import cx from 'classnames';
import bootstrap from 'bootstrap/dist/css/bootstrap.css';
import navbar from './navbar.css';
let styles = Object.assign({}, bootstrap, navbar);
public render() {
return (<Navbar cssModule={styles} className={cx(styles.navbarExpandSm, styles.navbarToggleableSm, styles.borderBottom, styles.boxShadow, styles.mb3)} light>[your menu here]</Navbar>);
}
This simply says the control to take the styles module and reference all the class names passed in classNames towards it. If you take a look at the mapToCssModules method, it is exactly what it does.
https://github.com/reactstrap/reactstrap/blob/d3cd4ea79dcaf478af5984f760ff1290406f62a5/src/utils.js#L53
In my case, it allows the control to pick up the original bootstrap styles and I can override what I need in my own module.

what does this syntax in styled-components actually mean?

I've just started using styled-components and saw that they call what i presume is a function like so:
import styled from "styled-components"
const Button = sytled.button` <--- this
// css goes here
`
I've never seem that syntax before and wanted to know if someone could point me to some docs about what it actually is.
It's called tagged template literals. The "tag" is the function before the template literal, which is called with its parameters being the template and template's variables. The parameters are as follow:
An array with all the string parts between the ${variables}.
First ${variable} of the template.
Second ${variable} of the template.
etc...
For example, I have written a function named tag that does the same as the function template literals use to process when you don't specify any tag function (a.k.a its default function):
function tag(stringParts, ...values){
return stringParts.reduce((accum, part, index) => accum + values[index-1] + part);
}
Calling it this way
tag`Hello, ${name}! I found ${count} results.`
yields the same result as
`Hello, ${name}! I found ${count} results.`
and the params fed to the tag function are ['Hello, ', '! I found ', ' results.'], name and count.
That's how you set the CSS rules for the <button> element.
So then you can use it as such:
<Button>Hello world</Button>
and all the styles you wrote above would get applied to all <Button> elements
Styled-components is a library used for styling react components.
import styled from "styled-components"
const Button = sytled.button` <--- this
// css goes here
`;
`` <-- these are template literals which was introduced in ES6.
styled is an object here and when you say styled.button it means that we are styling html tags. So you can style a div, container, h1 etc. You want to use standard css to style these html tags and styled-components create a random classname for the same.
let's say you want to style a div. You name it a Wrapper. The naming covention is first letter always capital.
const Wrapper = styled.div`
background: #c0c0aa; /* fallback for old browsers */
background: -webkit-linear-gradient(to right, #1cefff, #c0c0aa); /* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to right, #1cefff, #c0c0aa); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
height: 100%;
width: 100%;
`;
now you can wrap your content in render () of react.
<Wrapper>
//Your code in render of react class goes here
//thus instead of <div className = 'Wrapper'>
//you use the above code
//styled-components automatically generates random classnames solving major problems
</ Wrapper>
for more information see Max Stoiber's keynote at React Amsterdam.
https://www.styled-components.com/docs/basics#motivation

how to use common less variable with styled component?

Say I have a styled component, in index.jsx
import './index.less';
class Input extends React.Component {
...
}
and my index.less files looks:
.input{
color: #whiteColor;
}
This index.less has to work with the mixin.less that imported in the root project.
So my question is, even though I imported the mixin.less, it prompts variable #whiteColor not found. Any idea to solve this?
I have felt the same pain, why isn't my styled component resolving less variables?
The syntax is simple JavaScript, just do:
.input{
color: ${props => props.whiteColor};
// or
color: ${props => props.theme.whiteColor};
}
But, at my company, we had thousands of less components, and we really thought that the less syntax was cleaner and definitely faster to write. We developed Styless.
It is a babel plugin that parses less and generates javascript code. Add it to your .babelrc file.
{
"plugins": ["babel-plugin-styless"]
}
Then, we can do!!
const Input = styled.input`
#highlight: blue; // can be overwritten by theme or props
background: darken(#highlight, 5%); // make green darken by 5%
`;
Check here to see how to use the theme provider and load variable from your index.less!
You can try import the mixin.less in index.less
I have been trying the same than you.
But then I thought.. it is that what I really want? Because styled-components propose a different approach to having a modular structure for your styles.
https://www.styled-components.com/docs/advanced Check theming, is amazing powerful.
Because in styled components you define the variables with javascript.
And if you want color manipulation like less, sass, you can check https://github.com/erikras/styled-components-theme
Its like forgetting about less, and sass and moving it to a new style modules.
Still, if you want to keep your defined style classes, you can do that:
class MyComponent extends React.Component {
render() {
// Attach the passed-in className to the DOM node
return <div className={`some-global-class ${this.props.className}`} />;
}
}
Check the existing CSS usage from docs:
https://www.styled-components.com/docs/advanced#existing-css

Resources