Workaround for `TypeError: Cannot read property 'h' of undefined` and `TypeError: Cannot read property 'indexOf' of undefined`
See original GitHub issueI ran into the same error as https://github.com/cytoscape/cytoscape.js/issues/2453 when doing ReactDOM.render and snapshot testing. It works fine in the browser.
Workaround further down
// CustomCytoscape.jsx
import React, { useRef } from 'react'
import Cytoscape from 'react-cytoscapejs'
function CustomCytoscape({ headless, elements }) {
const layout = { name: 'preset' }
const cyRef = useRef()
return (
<Cytoscape
className={classes.cytoscape}
layout={layout}
cy={cy => {
cyRef.current = cy
}}
elements={elements}
stylesheet={stylesheet}
/>
)
}
// CustomCytoscape.test.js
import React from 'react'
import ReactDOM from 'react-dom'
import renderer from 'react-test-renderer'
import CustomCytoscape from '../CustomCytoscape'
describe('CustomCytoscape', () => {
const elements = []
it('renders without crashing', () => {
const div = document.createElement('div')
ReactDOM.render(
<CustomCytoscape elements={elements} />,
div
)
})
it('matches snapshot', () => {
const component = renderer.create(
<CustomCytoscape elements={elements} />
)
let tree = component.toJSON()
expect(tree).toMatchSnapshot()
})
})
returns TypeError: Cannot read property 'h' of undefined
it('renders without crashing', () => {
8 | const div = document.createElement('div')
> 9 | ReactDOM.render(<App />, div)
| ^
10 | })
11 |
12 | const component = renderer.create(<App />)
And TypeError: Cannot read property 'indexOf' of undefined
const component = renderer.create(<App />)
| ^
13 | let tree = component.toJSON()
14 | expect(tree).toMatchSnapshot()
15 | })
At the moment I cannot spend more time looking into it, but I will try to look into it when I can.
Workaround
// App.jsx
const App = () => {
const elements = []
const headless = process.env.NODE_ENV === 'test'
return (
<div className={classes.container}>
<CustomCytoscape elements={elements} headless={headless} />
</div>
)
}
// CustomCytoscape.jsx
import React, { useEffect, useRef } from 'react'
import cytoscape from 'cytoscape'
import Cytoscape from 'react-cytoscapejs'
function CustomCytoscape({ headless, elements }) {
const layout = { name: 'preset' }
const cyRef = useRef()
// Use cytoscape (non-react) if headless === true
useEffect(() => {
if (headless) {
cyRef.current = cytoscape({
container: document.getElementById('cyHeadless'),
layout,
elements,
style: stylesheet
})
}
}, [headless, elements, layout])
return headless ? (
<div id="cyHeadless" className={classes.cytoscape} />
) : (
<Cytoscape
className={classes.cytoscape}
layout={layout}
cy={cy => {
cyRef.current = cy
}}
elements={elements}
stylesheet={stylesheet}
/>
)
}
The following tests now works
CustomCytoscape.test.js
import React from 'react'
import ReactDOM from 'react-dom'
import renderer from 'react-test-renderer'
import CustomCytoscape from '../CustomCytoscape'
describe('CustomCytoscape', () => {
const elements = []
it('renders without crashing', () => {
const div = document.createElement('div')
ReactDOM.render(
<CustomCytoscape elements={elements} headless={true} />,
div
)
})
it('matches snapshot', () => {
const component = renderer.create(
<CustomCytoscape elements={elements} headless={true} />
)
let tree = component.toJSON()
expect(tree).toMatchSnapshot()
})
})
Issue Analytics
- State:
- Created 4 years ago
- Reactions:1
- Comments:6
Top Results From Across the Web
Cannot Read Property of Undefined in JavaScript - Rollbar
TypeError : Cannot read property of undefined occurs when a property is read or a function is called on an undefined variable.
Read more >"cannot read property 'indexOf' of undefined" - Stack Overflow
Right now, from the log, I can see the row number and the clean url. Problem is that the script stops with this...
Read more >Cannot read property 'index' of undefined - WebViewer
When I import the saved xpdfstring with annotManager.importAnnotations I have the following error: CoreControls.js:600 Uncaught TypeError: ...
Read more >How to Fix TypeError: Cannot read Property 'push' of ...
You call the method on a variable previously set to undefined . · You call the method on a variable before it has...
Read more >Cannot read properties of undefined' - JavaScript Debugging
How To Fix 'Uncaught TypeError : Cannot read properties of undefined ' - JavaScript Debugging. Watch later. Share. Copy link.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
If you’re doing UI tests, you should probably use a browser like Puppeteer. I can’t speak to the scope of @mattorp’s tests. He could answer better about how his approach fits in with his use-case.
Generally speaking, you could use a headless
cy
object for unit tests of your model – if the graph is a part of your model – but I would think that would be decoupled from React. I’m of the opinion that the majority of automated UI tests are low utility and high cost, but to each his own.For now, let’s close this issue since it seems to just be a Jest setup problem.
https://facebook.github.io/create-react-app/docs/running-tests
So Jest creates a fake
window
, which seems only sufficient for very basic rendering tests (e.g. simple divs). That is insufficient for testing real-world visualisations – and probably other things since Jest breaks fundamental assumptions about thewindow
object.So ultimately, this is a limitation of Jest and there would always need to be some kind of workaround. Even if something like a
headless
flag is exposed in the props of this component, you would need to detect Jest-mode versus app-mode and setheadless
appropriately.If you want to write automated UI tests, you probably need to use something more sophisticated than Jest. You would need to use something like Selenium or Mocha+Puppeteer or Jest+Puppeteer.