mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-05-29 09:02:03 +00:00
[change] modernize CheckBox
Rewrite CheckBox to use function components and hooks. Rewrite the tests to replace enzyme with testing-library.
This commit is contained in:
@@ -2,59 +2,62 @@
|
|||||||
|
|
||||||
import CheckBox from '../';
|
import CheckBox from '../';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
const checkboxSelector = 'input[type="checkbox"]';
|
function findCheckbox(container) {
|
||||||
|
return container.firstChild.querySelector('input');
|
||||||
|
}
|
||||||
|
|
||||||
describe('CheckBox', () => {
|
describe('CheckBox', () => {
|
||||||
describe('disabled', () => {
|
describe('disabled', () => {
|
||||||
test('when "false" a default checkbox is rendered', () => {
|
test('when "false" a default checkbox is rendered', () => {
|
||||||
const component = shallow(<CheckBox />);
|
const { container } = render(<CheckBox />);
|
||||||
expect(component.find(checkboxSelector).prop('disabled')).toBe(undefined);
|
expect(findCheckbox(container).disabled).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('when "true" a disabled checkbox is rendered', () => {
|
test('when "true" a disabled checkbox is rendered', () => {
|
||||||
const component = shallow(<CheckBox disabled />);
|
const { container } = render(<CheckBox disabled />);
|
||||||
expect(component.find(checkboxSelector).prop('disabled')).toBe(true);
|
expect(findCheckbox(container).disabled).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('onChange', () => {
|
describe('onChange', () => {
|
||||||
test('is called with the event object', () => {
|
test('is called with the event object', () => {
|
||||||
const onChange = jest.fn();
|
const onChange = jest.fn();
|
||||||
const component = shallow(<CheckBox onChange={onChange} value={false} />);
|
const { container } = render(<CheckBox onChange={onChange} value={false} />);
|
||||||
component.find('input').simulate('change', { nativeEvent: { target: { checked: true } } });
|
const checkbox = findCheckbox(container);
|
||||||
expect(onChange).toHaveBeenCalledWith({
|
checkbox.click(); // Needed to get ReactDOM to trigger 'change' event
|
||||||
nativeEvent: { target: { checked: true }, value: true }
|
expect(onChange).toHaveBeenCalled();
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('onValueChange', () => {
|
describe('onValueChange', () => {
|
||||||
test('when value is "false" it receives "true"', () => {
|
test('when value is "false" it receives "true"', () => {
|
||||||
const onValueChange = jest.fn();
|
const onValueChange = jest.fn();
|
||||||
const component = shallow(<CheckBox onValueChange={onValueChange} value={false} />);
|
const { container } = render(<CheckBox onValueChange={onValueChange} value={false} />);
|
||||||
component.find('input').simulate('change', { nativeEvent: { target: { checked: true } } });
|
const checkbox = findCheckbox(container);
|
||||||
|
checkbox.click(); // Needed to get ReactDOM to trigger 'change' event
|
||||||
expect(onValueChange).toHaveBeenCalledWith(true);
|
expect(onValueChange).toHaveBeenCalledWith(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('when value is "true" it receives "false"', () => {
|
test('when value is "true" it receives "false"', () => {
|
||||||
const onValueChange = jest.fn();
|
const onValueChange = jest.fn();
|
||||||
const component = shallow(<CheckBox onValueChange={onValueChange} value />);
|
const { container } = render(<CheckBox onValueChange={onValueChange} value />);
|
||||||
component.find('input').simulate('change', { nativeEvent: { target: { checked: false } } });
|
const checkbox = findCheckbox(container);
|
||||||
|
checkbox.click(); // Needed to get ReactDOM to trigger 'change' event
|
||||||
expect(onValueChange).toHaveBeenCalledWith(false);
|
expect(onValueChange).toHaveBeenCalledWith(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('value', () => {
|
describe('value', () => {
|
||||||
test('when "false" an unchecked checkbox is rendered', () => {
|
test('when "false" an unchecked checkbox is rendered', () => {
|
||||||
const component = shallow(<CheckBox value={false} />);
|
const { container } = render(<CheckBox value={false} />);
|
||||||
expect(component.find(checkboxSelector).prop('checked')).toBe(false);
|
expect(findCheckbox(container).checked).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('when "true" a checked checkbox is rendered', () => {
|
test('when "true" a checked checkbox is rendered', () => {
|
||||||
const component = shallow(<CheckBox value />);
|
const { container } = render(<CheckBox value />);
|
||||||
expect(component.find(checkboxSelector).prop('checked')).toBe(true);
|
expect(findCheckbox(container).checked).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+52
-63
@@ -10,12 +10,11 @@
|
|||||||
|
|
||||||
import type { ViewProps } from '../View';
|
import type { ViewProps } from '../View';
|
||||||
|
|
||||||
import applyNativeMethods from '../../modules/applyNativeMethods';
|
|
||||||
import createElement from '../createElement';
|
import createElement from '../createElement';
|
||||||
import StyleSheet from '../StyleSheet';
|
import StyleSheet from '../StyleSheet';
|
||||||
import UIManager from '../UIManager';
|
import UIManager from '../UIManager';
|
||||||
import View from '../View';
|
import View from '../View';
|
||||||
import React from 'react';
|
import React, { forwardRef, useImperativeHandle, useRef } from 'react';
|
||||||
|
|
||||||
type CheckBoxProps = {
|
type CheckBoxProps = {
|
||||||
...ViewProps,
|
...ViewProps,
|
||||||
@@ -26,74 +25,64 @@ type CheckBoxProps = {
|
|||||||
value?: boolean
|
value?: boolean
|
||||||
};
|
};
|
||||||
|
|
||||||
class CheckBox extends React.Component<CheckBoxProps> {
|
const CheckBox = forwardRef<CheckBoxProps, *>((props, ref) => {
|
||||||
_checkboxElement: HTMLInputElement;
|
const { color, disabled, onChange, onValueChange, style, value, ...other } = props;
|
||||||
|
|
||||||
static displayName = 'CheckBox';
|
const checkboxRef = useRef(null);
|
||||||
|
|
||||||
blur() {
|
useImperativeHandle(
|
||||||
UIManager.blur(this._checkboxElement);
|
ref,
|
||||||
}
|
() => {
|
||||||
|
return {
|
||||||
|
blur() {
|
||||||
|
UIManager.blur(checkboxRef.current);
|
||||||
|
},
|
||||||
|
focus() {
|
||||||
|
UIManager.focus(checkboxRef.current);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
[checkboxRef]
|
||||||
|
);
|
||||||
|
|
||||||
focus() {
|
function handleChange(event: Object) {
|
||||||
UIManager.focus(this._checkboxElement);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
color,
|
|
||||||
disabled,
|
|
||||||
/* eslint-disable */
|
|
||||||
onChange,
|
|
||||||
onValueChange,
|
|
||||||
/* eslint-enable */
|
|
||||||
style,
|
|
||||||
value,
|
|
||||||
...other
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const fakeControl = (
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
styles.fakeControl,
|
|
||||||
value && styles.fakeControlChecked,
|
|
||||||
// custom color
|
|
||||||
value && color && { backgroundColor: color, borderColor: color },
|
|
||||||
disabled && styles.fakeControlDisabled,
|
|
||||||
value && disabled && styles.fakeControlCheckedAndDisabled
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
const nativeControl = createElement('input', {
|
|
||||||
checked: value,
|
|
||||||
disabled: disabled,
|
|
||||||
onChange: this._handleChange,
|
|
||||||
ref: this._setCheckboxRef,
|
|
||||||
style: [styles.nativeControl, styles.cursorInherit],
|
|
||||||
type: 'checkbox'
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View {...other} style={[styles.root, style, disabled && styles.cursorDefault]}>
|
|
||||||
{fakeControl}
|
|
||||||
{nativeControl}
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_handleChange = (event: Object) => {
|
|
||||||
const { onChange, onValueChange } = this.props;
|
|
||||||
const value = event.nativeEvent.target.checked;
|
const value = event.nativeEvent.target.checked;
|
||||||
event.nativeEvent.value = value;
|
event.nativeEvent.value = value;
|
||||||
onChange && onChange(event);
|
onChange && onChange(event);
|
||||||
onValueChange && onValueChange(value);
|
onValueChange && onValueChange(value);
|
||||||
};
|
}
|
||||||
|
|
||||||
_setCheckboxRef = element => {
|
const fakeControl = (
|
||||||
this._checkboxElement = element;
|
<View
|
||||||
};
|
style={[
|
||||||
}
|
styles.fakeControl,
|
||||||
|
value && styles.fakeControlChecked,
|
||||||
|
// custom color
|
||||||
|
value && color && { backgroundColor: color, borderColor: color },
|
||||||
|
disabled && styles.fakeControlDisabled,
|
||||||
|
value && disabled && styles.fakeControlCheckedAndDisabled
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
const nativeControl = createElement('input', {
|
||||||
|
checked: value,
|
||||||
|
disabled: disabled,
|
||||||
|
onChange: handleChange,
|
||||||
|
ref: checkboxRef,
|
||||||
|
style: [styles.nativeControl, styles.cursorInherit],
|
||||||
|
type: 'checkbox'
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View {...other} ref={ref} style={[styles.root, style, disabled && styles.cursorDefault]}>
|
||||||
|
{fakeControl}
|
||||||
|
{nativeControl}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
CheckBox.displayName = 'CheckBox';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
root: {
|
root: {
|
||||||
@@ -143,4 +132,4 @@ const styles = StyleSheet.create({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default applyNativeMethods(CheckBox);
|
export default CheckBox;
|
||||||
|
|||||||
+1
-1
@@ -136,7 +136,7 @@ const Switch = forwardRef<SwitchProps, *>((props, ref) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View {...other} style={rootStyle}>
|
<View {...other} ref={ref} style={rootStyle}>
|
||||||
<View style={trackStyle} />
|
<View style={trackStyle} />
|
||||||
<View ref={thumbRef} style={thumbStyle} />
|
<View ref={thumbRef} style={thumbStyle} />
|
||||||
{nativeControl}
|
{nativeControl}
|
||||||
|
|||||||
Reference in New Issue
Block a user