I updated from react-native 0.39 to 0.41.2.
Now, WebView tests fail.
My example is more complicated (I shallow render a component containing a WebView) but I can reproduce it with the following snippet:
import React from 'react';
import { shallow } from 'enzyme'
import { WebView } from 'react-native';
describe('Test', () => {
it('test', () => {
shallow(<WebView />);
});
});
TypeError: Cannot read property 'decelerationRate' of undefined
at Object.<anonymous> (node_modules\react-native\Libraries\Components\WebView\WebView.ios.js:541:3254)
at Object.get WebView [as WebView] (node_modules\react-native\Libraries\react-native\react-native.js:69:22)
at Object.<anonymous>
I'm sure it's not an enzyme bug as I can reproduce it with 'react-test-renderer' as well.
?
cc @cpojer
I was able to get around the error by calling jest.unmock('ScrollView') before my test
It has something to do with Jest automatically mocking ScrollView, which WebView needs to validate propTypes in WebView.ios.js:
decelerationRate: ScrollView.propTypes.decelerationRate,
I'm still getting a console.error of Warning: Stateless function components cannot be given refs (See ref "webview" in StatelessComponent created by WebView). Attempts to access this ref will fail. even though my component is not stateless, but my tests are passing.
I encounter the same problem with jest and storyshots.
Just want to add that this still occurs in 0.42 and also affects MacOS.
Same problem here. The component is not even stateless
+1
I am getting this error as well, specifically:
Warning: Stateless function components cannot be given refs (See ref "webview" in StatelessComponent created by WebView). Attempts to access this ref will fail.
I wonder if this should be opened in a separate issue as the title doesn't reflect this particular problem.
Suggestion on a possible fix.
Currently inside of WebView.ios.js and WebView.android.js the RCTWebView component is setting its ref like this:
<RCTWebView
ref={RCT_WEBVIEW_REF}
where that constant is set like this
var RCT_WEBVIEW_REF = 'webview';
If however we set the ref with something like this:
<RCTWebView
ref={(wv) => { this.webview = wv }}
and of course change the reference to this in getWebViewHandle from
getWebViewHandle = (): any => {
return ReactNative.findNodeHandle(this.refs[RCT_WEBVIEW_REF]);
};
to
getWebViewHandle = (): any => {
return ReactNative.findNodeHandle(this.webview);
};
the Warning I mentioned above seems to go away.
ReactCompositeComponent is where this check
component._compositeType !== CompositeTypes.StatelessFunctional
is being made while attaching the refs in attachRef, which is causing the warning message we are seeing.
I'm still a little fuzzy on why this component is considered a StatelessFunctional component because it doesn't appear to be.
Have you tried jest.mock('WebView', () => 'WebView')? That worked for us.
Hi there! This issue is being closed because it has been inactive for a while. Maybe the issue has been fixed in a recent release, or perhaps it is not affecting a lot of people. Either way, we're automatically closing issues after a period of inactivity. Please do not take it personally!
If you think this issue should definitely remain open, please let us know. The following information is helpful when it comes to determining if the issue should be re-opened:
If you would like to work on a patch to fix the issue, contributions are very welcome! Read through the contribution guide, and feel free to hop into #react-native if you need help planning your contribution.
@benkraus jest.mock('WebView', () => 'WebView') worked in general, but doesn't work in the case where you're actually testing WebView functions. I could simulate events (through sinon & enzyme), but would miss picking up the renderLoad function call. @computerjazz's jest.unmock('ScrollView') did the trick for me and got me to 100% coverage for testing elements with a WebView.
this should be reopend because the bug is still there
@awreese Have you had success spying on the onLoad callbacks? I am trying to, but it seems that the test finished before the webview actually renders so my spies are never called.
@sfratini Yes, I believe so... I used Sinon for spying, and Enzyme for test rendering components... something along the lines of...
in componentWithWebView
<WebView
... other event props
onLoad={(e) => componentWithWebView.handleEvent(e)} // *** event handler ***
... other props
/>
in component test
...
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
import Enzyme, { shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import sinon from 'sinon';
Enzyme.configure({ adapter: new Adapter() });
import componentWithWebView from '...'; // *** import component with webview being tested ***
jest.unmock('scrollView'); // *** view note above for this ***
describe('Component with WebView test', () => {
... other tests
describe('Event Handlers handle events', () => {
let handleEventSpy;
let wrapper;
beforeAll(() => {
handleEventSpy = sinon.spy(componentWithWebView, 'handleEvent');
wrapper = shallow(<componentWithWebView/>);
});
beforeEach(() => {
handleEventSpy.reset();
});
... other event tests
it('Load event handled', () => {
const event = {
nativeEvent: {
url: "test",
}
};
expect(handleEventSpy.called).toBe(false);
wrapper.simulate('Load', event);
expect(handleEventSpy.calledOnce).toBe(true);
});
... other event tests
}
... other tests
}
Does this help you?
Thanks, yes! So you are doing the same as me, where you manually simulate the onLoad, instead of actually leaving the WebView load the URL.
Most helpful comment
I was able to get around the error by calling
jest.unmock('ScrollView')before my testIt has something to do with Jest automatically mocking ScrollView, which WebView needs to validate propTypes in WebView.ios.js:
decelerationRate: ScrollView.propTypes.decelerationRate,I'm still getting a console.error of
Warning: Stateless function components cannot be given refs (See ref "webview" in StatelessComponent created by WebView). Attempts to access this ref will fail.even though my component is not stateless, but my tests are passing.