How to test Accordion - jestjs

<Stack.Item>
{data?.map((item: any) => {
return (
<Accordion
header={item.faqTitle}
headerStyle={accordionHeaderStyles}
expanded={expandedId == item.faqId}
onExpandCollapse={() => onExpandCollapse(item.faqId)}
className={"faq-parent-accordian"}
>
<Stack.Item />
have above code but how do i can test attribute header ={item.faqTitle} having text or not?
test('can open accordion items to see the contents', () => {
const wrapper = shallow(<FaqComponent />);
expect(wrapper.find({ header: {item.faqTitle}}).prop("header")).toEqual("Step 1 - MS Sales Access");
});
getting error message, how do i can test header Item?

Related

How to test a chart to see if it renders correctly

I need help, I wanted to test whether the graph is rendering to me by searching for the word that should appear after the graph is rendered, but it gets an error.
I am trying to write tests in JEST
Below is a function drawing a graph
export interface CharProps {
data:Array<any>,
labels:Array<any>
}
export const Graph: React.FC<CharProps> = ({labels,data}) => {
const [chartData, setChartData]= useState({})
const chart = ()=>{
setChartData({
labels:labels,
datasets:[
{
label: 'Annual revenue',
fill: false,
}
]
})
}
useEffect(()=>{
chart()
},[])
return (
<>
<div className={chartBackground}>
<Line data={chartData} options={{responsive:true}}/>
</div>
</>
);
}
And my test below
describe('<Graph /> ', () => {
it('should be redner', () => {
render(<Graph data={[65]} labels={['monday']} ></Graph>);
expect(screen.getByText('monday')).toBeTruthy;
});
})
And my bug
TypeError: Cannot set property '_options' of undefined
8 | describe('<Graph /> ', () => {
9 | it('should be redner', () => {
> 10 | render(<Graph data={[65]} labels={['monday']} ></Graph>);
| ^
11 | expect(screen.getByText('monday')).toBeTruthy;
12 | });
13 | })
I cannot understand it, please help.
With the limited context available I can only guess what the problem is. But it seems like Graph is unknown to jest. Please check if you have properly imported the Graph component in your test file or test helper.
More information on jest and react: https://jestjs.io/docs/en/tutorial-react

React performing slow on extreme socket updates

I'm building a trading application and using node on the server side and react on client side.The current issue which I'm facing is regarding react performance on very frequents updates.
My process is describe as below.
The most common case I have is two tables displaying option data call and put. Each table have min of two rows and max of 8, so in total we'll have max 16 rows at single time. Each row can have up to 30 columns.
For updating I'm using a socket connection. Whenever a simple change occur in any of option column occurs an event emits from socket server which I'll be listening on client side.
After getting the data on client side via socket I can search for the specific row and column that where to update the data then re build the whole data of all 16 rows using the old data and new data and then dispatch the action... this updates occurs very frequently like 100s of 1000s of updates per millisecond and because of which whole table got re rendered and causing my app slow down.
I'm using redux to manage state in my react application
Here is an example with pure components no problem updating about 100 times a second:
const { useState, memo, useEffect, useRef } = React;
const COLUMS = 31;
const ITEM_COUNT = COLUMS * COLUMS;
const TIMER = 10;
const COLORS = ['red', 'green', 'blue'];
const nextColor = ((current) => () =>
COLORS[++current % COLORS.length])(0);
const next = ((num) => () => ++num % ITEM_COUNT)(-1);
const Item = memo(function Item({ color }) {
return (
<td
style={{
border: '1px solid black',
minWidth: '20px',
minHeight: '20px',
backgroundColor: color,
transitionDuration: '2s',
transitionTimingFunction: 'ease-out',
transitionProperty: 'color, background-color',
}}
>
</td>
);
});
const Row = memo(function Row({ items }) {
return (
<tr>
{items.map((item) => (
<Item key={item.id} color={item.color} />
))}
</tr>
);
});
const App = () => {
const r = useRef(0);
r.current++;
const [data, setData] = useState(
new Array(ITEM_COUNT)
.fill('')
.map((_, id) => ({ id, color: 'red' }))
.reduce((result, item, index) => {
if (index % COLUMS === 0) {
result.push([]);
}
result[result.length - 1].push(item);
return result;
}, [])
);
useEffect(() => {
const i = setInterval(
() =>
setData((data) => {
const change = next(), //id to change
color = nextColor(); //new value for color
return data.map(
(items) =>
//do not update items if id is not in this row
items.find(({ id }) => id === change)
? //update the one item that has id of change
items.map(
(item) =>
item.id === change
? { ...item, color } //change the color
: item //return the item unchanged
)
: items //id is not in this row return items unchanged
);
}),
TIMER
);
return () => clearInterval(i);
}, []);
return (
<div>
<h1>rendered: {r.current}</h1>
<table>
<tbody>
{data.map((items, index) => (
<Row key={index} items={items} />
))}
</tbody>
</table>
</div>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
I don't know why you're rerendering your components so frequently, but you can try throttling the updates to your redux store. This way you'll show all the latest data to your user without overburdening the CPU.
You can use throttle-debounce package to throttle your socket callback. Subsequent calls to the throttled function will only succeed if a given interval has been passed since the last call.

Formik odd (.value) need when updating formik.values

I manage a list of related elements in my form with a MUIDataTable(encapsulated here as CrudList) and a MUI Autocomplete.
I managed to add new elements through the autocomplete components onChange and to remove an element from a button using almost the same code. But I need to add .value on the second case Or it doesn't re-render.
What I'm doing wrong?
function RelatedModels({name, value ,model, tittle, columns, optionsSelector, onChange, ...fc}) {
const formik = useFormikContext();
const options = useSelector(createSelector(optionsSelector,
elements=> elements.filter(item => ! value.some(s=> item.idx === s.idx)))
);
const buttons = [
quickButton(
idx => () => {
const a =fc;
debugger;
//THIS NOT RE ENDER
formik.values[name]= value.filter(elem => idx !== elem.idx);
formik.setFieldTouched(name, true, false);
}
, 'Eliminar', <Delete/>)
];
return (
<Paper className="formPanel">
<h1>{tittle}</h1>
<Autocomplete
options={options}
onChange={(o, newElement)=> {
// THIS RE RENDER THE COMPONENT
formik.values[name].value = value.push(newElement);
formik.setFieldTouched(name, true, false);
}}
renderOption={ (option, state) =>
<span>{option.name}</span>
}
renderInput={params =>(
<MuiTextField {...params} label="Select to add" margin="normal" fullWidth/>)
}
/>
<CrudList Model={model} columns={columns.concat(buttons)} elements={value} buttons/>
</Paper> );
}
I include the component in the Formik as Follows
<Field as={RelatedModels}
name="accessories" model={Accessory} optionsSelector={availableAccessories}
tittle="Selecciona accesorio a aƱadir"
columns={accessoriesColumns}
/>

Jest / Enzyme html function is not multiline and indented

I'm snapshot testing the HTML from a React component:
describe('something', () => {
const wrapper = mount(
<MockProvider>
<MyCompoent />
</MockProvider>,
);
test('matches the snapshot', () => {
expect(wrapper.html()).toMatchSnapshot();
});
});
This works however the snapshot is minified:
exports[`MyCompoent something`] = `"<section class=\\"wrapper\\"><a class=\\"backLink\\" href=\\"#gift-type\\"><i class=\\"icon ArrowLeft backLinkIcon\\"><svg xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"0 0 64 64\\"><path fill=\\"currentColor\\" fill-rule=\\"nonzero\\" d=\\"M19.053 30.01h32.12v3h-32.38l13.28 13.28-2.121 2.121L13 31.458 30.004 16l2.018 2.22z\\"></path></svg></i>Back</a><div cla....
How can I have the HTML nicely multiline and indented? The same thing happens when I console.log(wrapper.html())
In my jest-config.js I already have this:
module.exports = {
snapshotSerializers: ['enzyme-to-json/serializer'],
};
If I don't use the render method (eg expect(wrapper).toMatchSnapshot();) then the multiline and indentation works fine.

Using fetch with react-excel-workbook

My problem is that Excel Export is exporting data to Excel before fetching is completed.
What I want to achieve: Fetch data when the button is clicked, then after all the data is fetched, export the data to excel. NB I do not want to fetch data when the component is rendered for the first time.
This is only one of my attempts:
class ExcelExport extends React.Component {
getDataForExport = () => {
get('/uri')
.then((response) => response.items)
.catch((error) => []);
};
render() {
return (
<Workbook element={<input type="button" value="Excel Export" />}>
<Workbook.Sheet data={() => this.getDataForExport()} name="Sheet A">
<Workbook.Column label="Foo" value="foo"/>
</Workbook.Sheet>
</Workbook>
);
}
}
Thank you for any help.
One possible solution to this problem would be to use the component state to store your data. So lets assume the call to get in your getDataForExport function returns data when the fetch is completed (the promise is resolved). In the then() call you could assign that data to the state like so:
class ExcelExport extends React.Component {
constructor() {
super();
this.state = { data: null }
}
getDataForExport = () => {
get('/uri')
.then((response) => {
this.setState({ data: response });
})
.catch((error) => []);
};
...
}
Then in your render function, you could add a button that triggers the data fetching and then you check whether this.state.data is null or whether some data is included and render different stuff depending on that:
render() {
return (
<Workbook element={<input type="button" value="Excel Export" onClick={this.getDataForExport.bind(this)} />}>
{this.state.data ||
<Workbook.Sheet data={this.state.data} name="Sheet A">
<Workbook.Column label="Foo" value="foo"/>
</Workbook.Sheet>}
</Workbook>
);
}
Hope this helps.

Resources