react-native-pager-view
react-native-pager-view copied to clipboard
Add example test to readme
Summary
Testing screens with ViewPager that uses setPage
function fails with the following error:
TypeError: Cannot read property 'Commands' of undefined
Tests like below will fail:
import React from 'react';
import {render, act} from '@testing-library/react-native';
import ViewPager from '@react-native-community/viewpager';
import {View} from 'react-native';
describe('ViewPager', () => {
test('view pager should move to next view', () => {
const viewPagerRef = React.createRef();
const {UNSAFE_getByType} = render(
<ViewPager ref={viewPagerRef}>
<View testID="page1" />
<View testID="page2" />
</ViewPager>,
);
expect(UNSAFE_getByType(ViewPager)._fiber.index).toBe(0);
act(() => {
viewPagerRef.current.setPage && viewPagerRef.current.setPage(1);
});
expect(UNSAFE_getByType(ViewPager)._fiber.index).toBe(1);
});
});
Environment info
react-native info
output:
System:
OS: macOS 10.15.6
CPU: (4) x64 Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz
Memory: 21.24 MB / 8.00 GB
Shell: 5.7.1 - /bin/zsh
Binaries:
Node: 12.18.3 - /var/folders/vl/7sf6krl17mz491vg6rqrlkr00000gn/T/yarn--1598293332713-0.5982209185240344/node
Yarn: 1.22.4 - /var/folders/vl/7sf6krl17mz491vg6rqrlkr00000gn/T/yarn--1598293332713-0.5982209185240344/yarn
npm: 6.14.6 - ~/.asdf/installs/nodejs/12.18.3/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
Managers:
CocoaPods: 1.9.3 - /usr/local/bin/pod
SDKs:
iOS SDK:
Platforms: iOS 13.6, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2
Android SDK:
API Levels: 28
Build Tools: 28.0.3, 30.0.1
System Images: android-28 | Intel x86 Atom
Android NDK: Not Found
IDEs:
Android Studio: 4.0 AI-193.6911.18.40.6626763
Xcode: 11.6/11E708 - /usr/bin/xcodebuild
Languages:
Java: 1.8.0_261 - /usr/bin/javac
Python: 2.7.16 - /Users/brunocrpontes/.asdf/shims/python
npmPackages:
@react-native-community/cli: Not Found
react: 16.11.0 => 16.11.0
react-native: 0.62.2 => 0.62.2
npmGlobalPackages:
*react-native*: Not Found
Library version: 4.1.6
Steps to reproduce
- Create a test with
<ViewPager />
- Take its ref like
<ViewPager ref={ref => viewPager = ref}
- Call
viewPager.setPage(/* page value */)
Describe what you expected to happen:
- Call
setPage
doesn't throw any errors. - Update value of index in component reference.
Hey, Thank you for reporting an issue. What platform is affected ?
From my POV, you should call it using current like below: https://github.com/react-native-community/react-native-viewpager/blob/master/example/ViewPagerExample.js#L103
I'm having the same issue, but only when running in test environment on Android platform. The test fails with the same error message the OP is having. I'm not using the library directly, but through a third party (react-native-scrollable-tab-view
), and they are using an Animated version with: Animated.createAnimatedComponent(ViewPager)
Hey, Thank you for reporting an issue. What platform is affected ?
From my POV, you should call it using current like below: https://github.com/react-native-community/react-native-viewpager/blob/master/example/ViewPagerExample.js#L103
It's happening in testing platform, in my Jest tests to be more exactly. Run it on device works fine.
I'm mocking package to workaround the issue, like below:
jest.mock('@react-native-community/viewpager', () => {
const RealComponent = jest.requireActual('@react-native-community/viewpager');
const React = require('react');
return class ViewPager extends RealComponent {
index = 0;
setPage = (page) => {
this.index = Math.max(
0,
Math.min(page, React.Children.count(this.props.children)),
);
};
};
});
Update: I added a test example that fails in issue description.
@brunocrpontes Thank you for providing an example. I don't understand, what would you like to achieve in your test ?
My test example isn't the best, is just to achieve error mentioned in issue.
In my case I built an paginated form using view pager as base component, part of my test is move to next page and try to capture some dependent instances of it, but in tests I can't move to next page. So current workaround is mocking it like my previous comment.
You cannot use below code
const RealComponent = jest.requireActual('@react-native-community/viewpager');
because viewpager has native implementation. There is no javascript logic inside.
If you would like to test VP, you need to mock this class and then mock implantation for onPageSelected
method.
@troZee understood, but why onPageSelected? I wish to move to next view pager page, the error came from "Commands" in setPage implementation.
VP changes pages using onPageSelected
, so why you want you use setPage
method ?
You can check in tests, if setPage
has been called, once eg button clicked
Hmm, I will try that and back with a feedback. Thanks @troZee for help!
Any updates on this? Still not sure how to test it
likewise, i have the same error as well
Any updates on this? Still not sure how to test it
likewise, i have the same error as well
What is an issue with mocking this component ?
Any updates on this? Still not sure how to test it
likewise, i have the same error as well
What is an issue with mocking this component ?
for some reason, the link that you gave is not valid anymore
do you have the updated link for that?
when using the above example, you get:
TypeError: Super expression must either be null or a function
So i'm also unsure how to mock. I have to use setPage
because I have an external button clicking through my onboarding
Any news? how to test?
Hey Guys! I think it's not the best approach but i managed to solve it with this mock:
jest.mock('react-native-pager-view', () => {
const RealComponent = jest.requireActual('react-native-pager-view')
const React = require('react')
return class ViewPager extends React.Component {
index = 0
setPage = page => {
this.index = Math.max(
0,
Math.min(page, React.Children.count(this.props.children))
)
}
render() {
return <RealComponent.default />
}
}
In my case I needed to test rendered content in the TabView (witch uses the PagerView). With this mock I was able to get it to work:
jest.mock("react-native-pager-view", () => {
const RealComponent = jest.requireActual("react-native-pager-view");
const React = require("react");
return class PagerView extends React.Component {
index = 0;
setPage = (page) => {
this.index = Math.max(
0,
Math.min(page, React.Children.count(this.props.children))
);
};
render() {
return (
<RealComponent.default>{this.props.children}</RealComponent.default>
);
}
};
});
Took me so long to get to the bottom of this - if anyone needs to test the tab change event and the onIndexChange
function, you can add this mock file or use jest.mock
as others have suggested:
// __mocks__/react-native-pager-view.js
import React from 'react';
import { View } from 'react-native';
/**
* This mock exists because there's no official jest setup for this library yet.
*
* @see {@link https://github.com/callstack/react-native-pager-view/issues/220}
* @see {@link https://github.com/callstack/react-native-pager-view/issues/481}
*/
class PagerView extends React.Component {
setPage(selectedPage: number) {
this.props.onPageSelected?.({ nativeEvent: { position: selectedPage } });
}
render() {
const { children, style, scrollEnabled, accessibilityLabel } = this.props;
return (
<View testID={this.props.testID} style={style} scrollEnabled={scrollEnabled} accessibilityLabel={accessibilityLabel}>
{children}
</View>
);
}
}
export { PagerView };
export default PagerView;
People sent several examples to test that component, so i'm closing this issue.