简体   繁体   中英

react native webview onNavigationStateChange is not a function (when running jest test)

I have a import { WebView } from 'react-native-webview'; from the react-native-community. Which is implemented in my react-native app like this:

<WebView
  key={ this.state.uri }
  source={{ uri: this.state.signedIn && this.state.shareUrl || this.state.uri }}
  style={{ width: '100%', height: '100%' }}
  onMessage={this.onMessage}
  onNavigationStateChange={this.setWebViewUrlChanged}
  onLoadEnd={syntheticEvent => {
    this.setState({ loading: false });
  }}
  onLoadStart={syntheticEvent => {
    this.setState({ loading: true });
  }}
/>

The onNavigationStateChange prop is called when I, from the running application withing the webview call window.location.realod(url)

My handler function looks like this:

setWebViewUrlChanged = webviewState => {
  if (webviewState.url !== this.state.initialUrl) {
    this.setState({ uri: webviewState.url });
  }
};

And is tested on phone and emulator, it works perfectly. I have even console logged state before/after and confirmed that state is updated and the function is called.

However, I am trying to test this with jest unit test.

it('should set webview uri', () => {
  console.log(snap.children[0].children[0].children[0].children[0].props);
  snap.children[0].children[0].children[0].children[0].props.onNavigationStateChange({ url: 'some-new-url' });
  expect(snap.state().uri).toEqual('some-new-url');
});

When running the test I get error:

TypeError: snap.children[0].children[0].children[0].children[0].props.onNavigationStateChange is not a function

and from the console.log line above I get the webviews props, where this function is missing:

  { style:
     [ { flex: 1 },
       { backgroundColor: '#ffffff' },
       { width: '100%', height: '100%' } ],
    source:
     { uri: 'https://test-domain.eu.ngrok.io/static/dashboard/index.html' },
    injectedJavaScript: undefined,
    bounces: undefined,
    scrollEnabled: undefined,
    pagingEnabled: undefined,
    cacheEnabled: true,
    decelerationRate: undefined,
    contentInset: undefined,
    automaticallyAdjustContentInsets: undefined,
    hideKeyboardAccessoryView: undefined,
    allowsBackForwardNavigationGestures: undefined,
    incognito: undefined,
    userAgent: undefined,
    onLoadingStart: [Function],
    onLoadingFinish: [Function],
    onLoadingError: [Function],
    onLoadingProgress: [Function],
    onMessage: [Function],
    messagingEnabled: true,
    onShouldStartLoadWithRequest: [Function],
    scalesPageToFit: undefined,
    allowsInlineMediaPlayback: undefined,
    mediaPlaybackRequiresUserAction: undefined,
    dataDetectorTypes: undefined,
    useSharedProcessPool: true,
    allowsLinkPreview: undefined,
    showsHorizontalScrollIndicator: undefined,
    showsVerticalScrollIndicator: undefined,
    directionalLockEnabled: undefined }

So in the test rendered webview only the onMessage function is as in my object, but all my onLoadStart/End and the onNavigationStateChange are not rendered.

But these functions that are missing works perfectly fine when project is compiled and running on device. How can I fix this, so that I can include unit tests for these functions?

The snap shot used in the test case is generated like so:

import renderer from 'react-test-renderer';

beforeEach(async () => {
  snapshot = renderer.create(<App />);
  snap = snapshot.toJSON();
});

I solved it by switching test renderer. I installed enzyme , enzyme-to-json , enzyme-adapter-react-16

Test modified:

describe('with setting', () => {
  let snapshot;

  beforeEach(async () => {
    // some mocking of asyncStorage
  });

  it('should match snapshot', async () => {
    snapshot = shallow(<App />)
    await new Promise((resolve) => setTimeout(resolve, 100)); // to allow async componentDidMount to finish.
    expect(snapshot).toMatchSnapshot()
  });

  it('should set webview uri', () => {
    snapshot.find('WebView').props().onNavigationStateChange({ url: 'some-new-url' });
    expect(snapshot.state().uri).toEqual('some-new-url');
  });
});

The shallow function comes from configuring enzyme for jest in setup.js

import Enzyme, { shallow, render, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

// React 16 Enzyme adapter
Enzyme.configure({ adapter: new Adapter() });

// Make Enzyme functions available in all test files without importing
global.shallow = shallow;
global.render = render;
global.mount = mount;

The setup.js is pointet to in the jest configuration (in my case in package.json)

"jest": {
    "preset": "react-native",
    "snapshotSerializers": [
      "enzyme-to-json/serializer"
    ],
    "setupFiles": [
      "<rootDir>/react-native/jest/setup.js"
    ]
  }

Hope this will help others who have issues with misalignment of compiled rendered components and mocked (test) rendered component.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM