J'ai écrit un bouton personnalisé (MyStyledButton
) basé sur material-ui Button
.
import React from "react";
import { Button } from "@material-ui/core";
import { makeStyles } from "@material-ui/styles";
const useStyles = makeStyles({
root: {
minWidth: 100
}
});
function MyStyledButton(props) {
const buttonStyle = useStyles(props);
const { children, width, ...others } = props;
return (
<Button classes={{ root: buttonStyle.root }} {...others}>
{children}
</Button>
);
}
export default MyStyledButton;
Il est stylisé en utilisant un thème et cela spécifie que le backgroundColor
doit être une nuance de jaune (spécialement #fbb900
)
import { createMuiTheme } from "@material-ui/core/styles";
export const myYellow = "#FBB900";
export const theme = createMuiTheme({
overrides: {
MuiButton: {
containedPrimary: {
color: "black",
backgroundColor: myYellow
}
}
}
});
Le composant est instancié dans mon index.js
Principal et enveloppé dans le theme
.
<MuiThemeProvider theme={theme}>
<MyStyledButton variant="contained" color="primary">
Primary Click Me
</MyStyledButton>
</MuiThemeProvider>
Si j'examine le bouton dans Chrome DevTools, le background-color
Est "calculé" comme prévu. C'est également le cas dans Firefox DevTools.
Cependant, lorsque j'écris un test JEST pour vérifier le background-color
Et que j'interroge le style de nœud DOM du bouton à l'aide de getComputedStyles()
j'obtiens transparent
et le test échoue.
const wrapper = mount(
<MyStyledButton variant="contained" color="primary">
Primary
</MyStyledButton>
);
const foundButton = wrapper.find("button");
expect(foundButton).toHaveLength(1);
//I want to check the background colour of the button here
//I've tried getComputedStyle() but it returns 'transparent' instead of #FBB900
expect(
window
.getComputedStyle(foundButton.getDOMNode())
.getPropertyValue("background-color")
).toEqual(myYellow);
J'ai inclus un CodeSandbox avec le problème exact, le code minimum à reproduire et l'échec du test JEST.
Je me suis rapproché, mais je n'ai pas encore trouvé de solution.
Le problème principal est que MUIButton injecte une balise à l'élément pour alimenter les styles. Cela ne se produit pas dans votre test unitaire. J'ai pu faire fonctionner cela en utilisant createMount que les tests de matériaux utilisent.
Après ce correctif, le style s'affiche correctement. Cependant, le style calculé ne fonctionne toujours pas. Il semble que d'autres ont rencontré des problèmes avec la gestion correcte des enzymes - donc je ne sais pas si c'est possible.
Pour arriver là où j'étais, prenez votre extrait de test, copiez-le en haut, puis changez votre code de test en:
const myMount = createMount({ strict: true });
const wrapper = myMount(
<MuiThemeProvider theme={theme}>
<MyStyledButton variant="contained" color="primary">
Primary
</MyStyledButton>
</MuiThemeProvider>
);
class Mode extends React.Component {
static propTypes = {
/**
* this is essentially children. However we can't use children because then
* using `wrapper.setProps({ children })` would work differently if this component
* would be the root.
*/
__element: PropTypes.element.isRequired,
__strict: PropTypes.bool.isRequired,
};
render() {
// Excess props will come from e.g. enzyme setProps
const { __element, __strict, ...other } = this.props;
const Component = __strict ? React.StrictMode : React.Fragment;
return <Component>{React.cloneElement(__element, other)}</Component>;
}
}
// Generate an enhanced mount function.
function createMount(options = {}) {
const attachTo = document.createElement('div');
attachTo.className = 'app';
attachTo.setAttribute('id', 'app');
document.body.insertBefore(attachTo, document.body.firstChild);
const mountWithContext = function mountWithContext(node, localOptions = {}) {
const strict = true;
const disableUnnmount = false;
const localEnzymeOptions = {};
const globalEnzymeOptions = {};
if (!disableUnnmount) {
ReactDOM.unmountComponentAtNode(attachTo);
}
// some tests require that no other components are in the tree
// e.g. when doing .instance(), .state() etc.
return mount(strict == null ? node : <Mode __element={node} __strict={Boolean(strict)} />, {
attachTo,
...globalEnzymeOptions,
...localEnzymeOptions,
});
};
mountWithContext.attachTo = attachTo;
mountWithContext.cleanUp = () => {
ReactDOM.unmountComponentAtNode(attachTo);
attachTo.parentElement.removeChild(attachTo);
};
return mountWithContext;
}