I have to test a very unusual case, in my test I should click to some component which is wrapped by from material-ui and it is inside the List from react-vertualized.
I have dived to it -
wrapper
.find(TreeView)
.dive()
.find(AutoSizer)
.renderProp('children', {})
.find(VirtualizedTree)
.dive()
.renderProp('rowRenderer', { index: 0, props: {...} });
And if I debug it I see this result -
<WithStyles(TreeNode) data-test="projected-tree" components={{...}} onSelectToggle={[Function]} onExpandToggle={[Function]} width={...} style={...} node={{...}} level={0} isOdd={true} />
The component which I want to click is inside the TreeNode, but when I try to dive I receive the error related to my custom theme which I use in my project, this happening because has lost the connection to the custom theme.
I think this happening because it has been rendered through the rowRenderer property of List.
Maybe somebody has any ideas on how to pass the custom theme inside the List.rowRenderer?
you need to mock the width and height to make AutoSizer return a width to children can showup
you can use this function mockOffsetSize
// AutoSizer uses offsetWidth and offsetHeight.
// Jest runs in JSDom which doesn't support measurements APIs.
function mockOffsetSize(width, height) {
Object.defineProperty(HTMLElement.prototype, 'offsetHeight', {
configurable: true,
value: height,
});
Object.defineProperty(HTMLElement.prototype, 'offsetWidth', {
configurable: true,
value: width,
});
}
ref: https://github.com/bvaughn/react-virtualized/blob/master/source/AutoSizer/AutoSizer.jest.js#L68
Related
I'm working with Next.js and using a react-spring library to get an animation for a bottomsheet component. It works, however there is a warning appears:
Warning: Prop style did not match. Server: "transform:translate3d(0,Infinitypx,0)" Client: "transform:translate3d(0,652px,0)"
I've carefully investigated this warning and know that it's about incorrect rendering of the HTML element on the server and on the client side. It's clear that on the server side there is no viewport height and thus react-spring can't calculate normally the final value and Next.js registers it as an one value with Infinity and then blames on the client side when the value is calculated correctly due to available viewport height.
I'm wondering what is the best way to rid of this error?
Unfortunatelly I can't catch the react-spring calculation stage and to set a correct value.Tere is no API to do it and basically I just don't know the user's viewport height.
I've thinking about the using indexOf for the value and check if the Infinity presented and replace it for ex: by 0
however it still doesn't solve a problem as the final value will be different anyway.
Maybe someone has an idea or some link to docs etc. where I could find a solution for that?
Basically it's just a warning but I'd like to fix it anyway.
Here is the example code:
import { a, config, useSpring } from '#react-spring/web';
export function BottomSheet({propsHeight}) {
const finalHeight = propsHeight || height - 62;
const display = y.to((py) => (py < finalHeight ? 'flex' : 'none'));
const [{ y }, api] = useSpring(() => ({ y: finalHeight }));
const open = (dragEvent?: any) => {
const canceled = dragEvent?.canceled;
// when cancel is true, it means that the user passed the upwards threshold
// so need to change the spring config to create a nice wobbly effect
api.start({
y: 0,
immediate: false,
config: canceled ? config.wobbly : config.stiff,
});
};
const close = (velocity = 0) => {
api.start({
y: finalHeight,
immediate: false,
onResolve() {
if (onClose) {
onClose();
}
},
config: { ...config.stiff, velocity },
});
};
useEffect(() => {
// provide open/close actions to parent control
getActions(open, close);
}, []);
// pseudo hmtl. Removed all other markup to simplify things
return (<a.div
style={{
y, // Here is the problem of the server & client incorrect values
}}
/>)
}
I highly appreciate any help!
Kind Regards
The only one solution I've found so far for this use case it's rendering the component on client side only and, basically, it makes sense because this code is based on the browser API. I don't see any other possible solutions
To achieve it you can use dymanic imports and Next.js supports them well: here is the docs
You should disable the SSR in the import options and the component will be rendered on the client side only.
Like this:
import dynamic from 'next/dynamic';
const BottomSheetDynamic = dynamic(
() =>
import('#mylibrary/components/bottomsheet/BottomSheet').then(
//this component doesn't have default import so should do it in this way
(mod) => mod.BottomSheetexport
),
{
ssr: false,
}
);
I'm using jest and #testing-library for my units tests in react (typescript).
I have a custom datatable component that uses useMediaQuery to display or not some elements on mobile.
const isDesktop = useMediaQuery({
query: '(min-width: 768px)',
});
With this boolean, in my case, I choosed to hide the row selection on mobile with a simple ternary.
In my test, I want to check if the selection checkbox is in the document, but of course it's not.
By removing the mobile condition, the test passes with success, because we render the selection checkbox no matter the screen size.
I conclude that my test environment is like a small screen, so the mobile condition returns true everytime and I cannot test my checkboxes.
(When I say mobile condition, it's of course based on the isDesktop).
Is there a way to mock jest and say before each test "i want that the test screen size is 1500pw width" or something like that ?
I tried something that I saw on an other topic but it does not work for me :
window.matchMedia = jest.fn().mockImplementation((query) => ({
matches: query === `(min-width: ${utils.breakpoints.md}px)`,
media: '',
onchange: null,
addListener: jest.fn(),
removeListener: jest.fn(),
}));
I am trying to simulate a click on a material-ui checkbox. I have tried
selectAllCheckbox.simulate("change", { target: { checked: true } });
and
act(() => {
selectAllCheckbox.props().onClick();
});
I have tried re-finding the item and updating the wrapper, and I cannot get the checked prop to change.
I feel like I missing something fundamental.
I have a codesandbox here: https://codesandbox.io/s/enzymetestformaterialuitable-t1ruq
the sandbox has a material-ui table (lifted from their demos page).
TIA
I got a hand from a few sources including https://github.com/airbnb/enzyme/issues/216
complete sandbox https://codesandbox.io/s/enzymetestformaterialuitable-updb9 with tests passing
check the 4th checkbox on the table:
let innerInputElement5 = wrapper
.find('[role="checkbox"]')
.hostNodes()
.at(4);
innerInputElement5.simulate("click");
check the indeterminate checkbox in the header:
let selectAllCheckboxInHeader = wrapper
.find(TableHead)
.find('input[type="checkbox"]')
.simulate("change", { target: { checked: true } });
I am using React-Slick (https://github.com/akiran/react-slick) for my project.
I want to be able to dynamically change the settings that I provide to my slider.
For slickjs (https://github.com/kenwheeler/slick) this can be done using slickSetOption.
I realized that this is not possible in React Slick after reading documentation.
The following was also posted by one of the contributors to the plugin:
slickSetOption will not be implemented, those effects be achieved by
passing props via state from the wrapper component
This made me think that it should be possible to in fact change the settings of the slider in a dynamic way.
My implementation looks like this
<Slider
dots={true}
infinite={true}
speed={500}
slidesToShow={1}
slidesToScroll={1}
autoplaySpeed={2000}
autoplay={props.autoplay} // even if the value is changed, autoplay stays to it's initial setting
>
{images}
</Slider>
Using React Slick's playground I've put together this to demonstrate the issue:
https://codesandbox.io/s/react-slick-playground-unyot
What am I missing here?
I think this is a bug in the component, probably some internal state is not changed. As a workaround, you can change the key prop when the autoplay prop change, this will force the Slider component to be recreated :
state = {
dots: true,
autoplay: false,
sliderKey: Date.now()
};
useAutoplay() {
this.setState({
autoplay: true,
sliderKey: Date.now()
});
}
<Slider key={this.state.sliderKey} {...this.state}>
</Slider>
Complete code : https://codesandbox.io/s/react-slick-playground-dx957
In my React application, I am using 'Editor.jsx component (which is just a wrapper around code-mirror, in case I need to provide frills around the actual CodeMirror-view).
The in which the rendered component from attached file is added to, has height of 100% and other components similar to CodeMirror do use that full height.
The CodeMirror component however only shows 15 lines (and i have to scroll to get to the ones below).
The code is very similar to the sample from github. The height property in getInitialState() also has no effect (neither does the containing ).
import React from 'react';
var CodeMirror = require('react-codemirror');
// fishing this 'require' out has caused severe headache and cost time.
// IF not included, default bootstrap style used. must override it with this.
// but for react-codemirror component we need this one!!!
// REF http://dorianpula.ca/2015/10/07/adding-a-code-editor-to-rookeries/
require("codemirror/lib/codemirror.css");
require('codemirror/mode/javascript/javascript');
require('codemirror/mode/python/python');
var DFLTS = {
javascript: 'var component = {\n\tname: "react-codemirror",\n\tauthor: "Jed Watson",\n\tforUseBy: "KB"}',
python: 'print "hello python world"'
}
export default React.createClass ({
localOnCodeChange(newCode) {
this.props.onCodeChange(newCode)
},
getInitialState() {
return {
code: DFLTS.javascript,
readOnly: false,
mode: 'javascript',
height:"100%",
viewportMargin: "Infinity"
};
},
componentDidMount() {
CodeMirror.setSize("100%", 1000);
},
changeMode(e) {
// add python later.
// no-op
},
toggleRreadOnly() {
this.setState({
readOnly: !this.state.readOnly
}, () => this.refs.editor.focus());
},
interact(cm) {
console.log(cm.getValue());
},
render() {
var options = {
lineNumbers: true,
readOnly: this.state.readOnly,
mode: this.state.mode
};
return (
<CodeMirror ref="editor" value={this.props.code} onChange={this.props.onCodeChange} options={options} interact={this.interact}/>
)
}
});
Any pointers, greatly appreciated.
The .CodeMirror class in this library appears to have a hard-coded height: 300px in it and there's an unanswered question in their issues about being able to set the height. If you put .CodeMirror { min-height: 100% } in your CSS that might do the trick.
Alternatively pass a className to <CodeMirror> (it will get added to the classes) that sets a min height, or a height with !important, or just greater specificity.
(Tsk tsk to components that you have to fight with :))
if you need to dynamically change the height, or simply dont want to use css you can use ref
const codemirrorRef = React.useRef();
React.useEffect(() => {
const current = codemirrorRef.current.editor.display.wrapper.style.height = "1000px";
});
<CodeMirror
[...]
ref={codemirrorRef}
/>
codemirrorRef.current.editor.display.wrapper contains the div element. From there you can do anything you would do if you did document.getElementById('#id')
I was able to get the height to override by adding an addition to the existing CodeMirror class in my CSS file as follows:
.CodeMirror {
height: 100% !important
}
it only applied the change after adding !important to force it to override the existing class which is hard coded to 300 pixels.