我围绕 ScrollView 编写了一个简单的包装组件,它根据给定的可用高度启用/禁用滚动:
import React, {useCallback, useEffect, useRef, useState} from 'react';
import {Keyboard, ScrollView} from 'react-native';
import {deviceHeight} from '../../../platform';
export default function ScrollingForm({
availableHeight = deviceHeight,
children,
}) {
const [scrollEnabled, setScrollEnabled] = useState(true);
const [formHeight, setFormHeight] = useState(0);
const scrollingForm = useRef(null);
const checkScrollViewEnabled = useCallback(() => {
setScrollEnabled(formHeight > availableHeight);
}, [availableHeight, formHeight]);
const onFormLayout = async event => {
await setFormHeight(event.nativeEvent.layout.height);
checkScrollViewEnabled();
};
useEffect(() => {
Keyboard.addListener('keyboardDidHide', checkScrollViewEnabled);
// cleanup function
return () => {
Keyboard.removeListener('keyboardDidHide', checkScrollViewEnabled);
};
}, [checkScrollViewEnabled]);
return (
<ScrollView
ref={scrollingForm}
testID="scrollingForm"
keyboardDismissMode="on-drag"
keyboardShouldPersistTaps="handled"
scrollEnabled={scrollEnabled}
onLayout={onFormLayout}
onKeyboardDidShow={() => setScrollEnabled(true)}>
{children}
</ScrollView>
);
}
我需要为此组件编写单元测试。到目前为止,我有:
import React from 'react';
import {Keyboard} from 'react-native';
import {render} from 'react-native-testing-library';
import {Text} from '../..';
import ScrollingForm from './ScrollingForm';
describe('ScrollingForm', () => {
Keyboard.addListener = jest.fn();
Keyboard.removeListener = jest.fn();
let renderer;
describe('keyboard listener', () => {
it('renders text with default props', () => {
renderer = render(
<ScrollingForm>
<Text>Hello World!</Text>
</ScrollingForm>,
);
expect(Keyboard.addListener).toHaveBeenCalled();
});
it('should call listener.remove on unmount', () => {
renderer = render(
<ScrollingForm>
<Text>Goodbye World!</Text>
</ScrollingForm>,
);
renderer.unmount();
expect(Keyboard.removeListener).toHaveBeenCalled();
});
});
});
我还想确认,如果可用高度大于表单高度,则在布局上,scrollEnabled 正确设置为 false。我试过这样的事情:
it('sets scrollEnabled to false onFormLayout width 1000 height', () => {
mockHeight = 1000;
const {getByTestId} = render(
<ScrollingForm availableHeight={500}>
<Text>Hello World!</Text>
</ScrollingForm>,
);
const scrollingForm = getByTestId('scrollingForm');
fireEvent(scrollingForm, 'onLayout', {
nativeEvent: {layout: {height: mockHeight}},
});
expect(scrollingForm.props.scrollEnabled).toBe(false);
});