-
Notifications
You must be signed in to change notification settings - Fork 932
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add snapshot test suite for React Native support #328
Changes from all commits
797b463
2f6df10
c2d4c95
c223adc
e5e9c44
21baedb
4619b81
4d35baf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"presets": ["env", "react-native"] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`renders with React Native components 1`] = ` | ||
<View> | ||
<TextInput | ||
allowFontScaling={true} | ||
aria-activedescendant={null} | ||
aria-autocomplete="list" | ||
aria-expanded={false} | ||
autoComplete="off" | ||
id="downshift-0-input" | ||
onBlur={[Function]} | ||
onChangeText={[Function]} | ||
onKeyDown={[Function]} | ||
role="combobox" | ||
value="" | ||
/> | ||
<View> | ||
<Text | ||
accessible={true} | ||
allowFontScaling={true} | ||
ellipsizeMode="tail" | ||
id="downshift-0-item-0" | ||
onMouseDown={[Function]} | ||
onMouseMove={[Function]} | ||
onPress={[Function]} | ||
> | ||
foo | ||
</Text> | ||
<Text | ||
accessible={true} | ||
allowFontScaling={true} | ||
ellipsizeMode="tail" | ||
id="downshift-0-item-1" | ||
onMouseDown={[Function]} | ||
onMouseMove={[Function]} | ||
onPress={[Function]} | ||
> | ||
bar | ||
</Text> | ||
</View> | ||
</View> | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* eslint-disable react/prop-types */ | ||
// eslint-disable-next-line import/no-unassigned-import | ||
import {Text, TextInput, View} from 'react-native' | ||
import React from 'react' | ||
|
||
// Note: test renderer must be required after react-native. | ||
import TestRenderer from 'react-test-renderer' | ||
|
||
import Downshift from '../../../dist/downshift.native.cjs' | ||
|
||
test('renders with React Native components', () => { | ||
const RootView = ({innerRef, ...rest}) => <View ref={innerRef} {...rest} /> | ||
const renderSpy = jest.fn(({getRootProps, getInputProps, getItemProps}) => ( | ||
<RootView {...getRootProps({refKey: 'innerRef'})}> | ||
<TextInput {...getInputProps()} /> | ||
<View> | ||
<Text {...getItemProps({item: 'foo', index: 0})}>foo</Text> | ||
<Text {...getItemProps({item: 'bar', index: 1})}>bar</Text> | ||
</View> | ||
</RootView> | ||
)) | ||
const element = <Downshift render={renderSpy} /> | ||
const renderer = TestRenderer.create(element) | ||
expect(renderSpy).toHaveBeenCalledWith( | ||
expect.objectContaining({ | ||
isOpen: false, | ||
highlightedIndex: null, | ||
selectedItem: null, | ||
inputValue: '', | ||
}), | ||
) | ||
const tree = renderer.toJSON() | ||
expect(tree).toMatchSnapshot() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could remove this snapshot, but I think ensuring that we render the basic set of React Native components here, while applying the functions from Downshift, is a fair trade-off for using a snapshot. |
||
}) | ||
|
||
test('can use children instead of render prop', () => { | ||
const RootView = ({innerRef, ...rest}) => <View ref={innerRef} {...rest} /> | ||
const renderSpy = jest.fn(({getRootProps, getInputProps, getItemProps}) => ( | ||
<RootView {...getRootProps({refKey: 'innerRef'})}> | ||
<TextInput {...getInputProps()} /> | ||
<View> | ||
<Text {...getItemProps({item: 'foo', index: 0})}>foo</Text> | ||
<Text {...getItemProps({item: 'bar', index: 1})}>bar</Text> | ||
</View> | ||
</RootView> | ||
)) | ||
const element = <Downshift>{renderSpy}</Downshift> | ||
TestRenderer.create(element) | ||
expect(renderSpy).toHaveBeenCalledTimes(1) | ||
}) | ||
|
||
test('calls onChange when TextInput changes values', () => { | ||
const onChange = jest.fn() | ||
const Input = jest.fn(props => <TextInput {...props} />) | ||
|
||
const RootView = ({innerRef, ...rest}) => <View ref={innerRef} {...rest} /> | ||
const renderSpy = jest.fn(({getRootProps, getInputProps, getItemProps}) => ( | ||
<RootView {...getRootProps({refKey: 'innerRef'})}> | ||
<Input {...getInputProps({onChange})} /> | ||
<View> | ||
<Text {...getItemProps({item: 'foo', index: 0})}>foo</Text> | ||
<Text {...getItemProps({item: 'bar', index: 1})}>bar</Text> | ||
</View> | ||
</RootView> | ||
)) | ||
const element = <Downshift>{renderSpy}</Downshift> | ||
TestRenderer.create(element) | ||
expect(renderSpy).toHaveBeenCalledTimes(1) | ||
|
||
const [[firstArg]] = Input.mock.calls | ||
expect(firstArg).toMatchObject({ | ||
// TODO: We shouldn't need to know about the internals of how we're affecting the TextInput and what props we're supplying. | ||
// See https://github.com/paypal/downshift/issues/361 | ||
onChangeText: expect.any(Function), | ||
}) | ||
const fakeEvent = 'foobar' | ||
firstArg.onChangeText(fakeEvent) | ||
|
||
expect(onChange).toHaveBeenCalledTimes(1) | ||
expect(onChange).toHaveBeenCalledWith(fakeEvent) | ||
}) | ||
|
||
/* | ||
eslint | ||
react/prop-types: 0, | ||
import/extensions: 0, | ||
import/no-unresolved: 0 | ||
*/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
const jestConfig = require('kcd-scripts/config').jest | ||
|
||
module.exports = Object.assign(jestConfig, { | ||
preset: 'react-native', | ||
testEnvironment: 'node', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This song and dance felt pretty gnarly, but this is the base config I've found that allows for sharing of |
||
transformIgnorePatterns: ['<rootDir>/node_modules/(?!react-native)/'], | ||
rootDir: '../../', | ||
roots: ['.'], | ||
testMatch: ['<rootDir>/other/react-native/__tests__/**/*.js?(x)'], | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm normally not a huge fan of huge snapshots (learn more). But I think this is ok because I don't think we plan on making changes that would affect this snapshot very often anyway. But if there's a way we can avoid these snapshots by making more explicit assertions I think I'd be happier with that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. I tried thinking of a better way to get here, instead of using snapshots, but I'm unsure of what other methods we could use to test the React Native renderer.
We could emulate the Preact tests and use a spy to ensure that
render
successfully gets called, but I don't think that's any better than these snapshots.I'll see if I can come up some better assertions here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ended up writing some tests that were similar to those Preact tests and I feel like it's much clearer as to what we're testing now! 216c531
Let me know what you think.