* Copyright (c) 2024 Huawei Technologies Co., Ltd.
*
* This source code is licensed under the MIT license found in the
* LICENSE-MIT file in the root directory of this source tree.
*/
import { TestSuite, TestCase } from '@rnoh/testerino';
import {
Keyboard,
StyleSheet,
TextInput,
KeyboardEvent,
Dimensions,
} from 'react-native';
import { Button } from '../components';
import { useEffect } from 'react';
import { EmitterSubscription } from 'react-native/Libraries/vendor/emitter/EventEmitter';
export function KeyboardTest() {
return (
<TestSuite name="Keyboard">
<TestCase
itShould="not crash when using keyboard module"
fn={({ expect }) => {
expect(Keyboard.isVisible()).to.be.false;
}}
/>
<TestCase modal itShould="dismiss keyboard on button press">
<TextInput style={styles.textInput} />
<Button label="Dismiss keyboard" onPress={() => Keyboard.dismiss()} />
</TestCase>
<TestCase
modal
skip
initialState={{
keyboardDidHide: false,
keyboardDidShow: true,
keyboardEvent: {} as KeyboardEvent,
}}
itShould="not open the keyboard after opening the modal"
arrange={({ setState, reset }) => {
return (
<KeyboardEventsView
listenToShow
checkIfKeyboardIsVisible
onSetState={setState}
reset={reset}
/>
);
}}
assert={({ expect, state }) => {
expect(state.keyboardDidShow).to.be.false;
expect(state.keyboardDidHide).to.be.false;
}}
// https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/380
/>
<TestCase
modal
initialState={{
keyboardDidHide: false,
keyboardDidShow: false,
keyboardEvent: {} as KeyboardEvent,
}}
itShould="pass after opening the keyboard"
arrange={({ setState, reset }) => {
return (
<KeyboardEventsView
listenToShow
dismissOnReset
onSetState={setState}
reset={reset}
/>
);
}}
assert={({ expect, state }) => {
expect(state.keyboardDidShow).to.be.true;
expect(state.keyboardDidHide).to.be.false;
expect(state.keyboardEvent.endCoordinates.height).to.be.greaterThan(
0,
);
expect(state.keyboardEvent.endCoordinates.width).to.be.greaterThan(0);
expect(state.keyboardEvent.endCoordinates.screenY).to.be.lessThan(
Dimensions.get('window').height,
);
expect(state.keyboardEvent.endCoordinates.screenX).to.be.equal(0);
}}
/>
<TestCase
modal
initialState={{
keyboardDidHide: false,
keyboardDidShow: false,
keyboardEvent: {} as KeyboardEvent,
}}
itShould="pass after dismissing the keyboard"
arrange={({ setState, reset }) => {
return (
<KeyboardEventsView
listenToHide
showDismissButton
onSetState={setState}
reset={reset}
/>
);
}}
assert={({ expect, state }) => {
expect(state.keyboardDidHide).to.be.true;
expect(state.keyboardDidShow).to.be.false;
expect(state.keyboardEvent.endCoordinates.height).to.be.equal(0);
expect(state.keyboardEvent.endCoordinates.width).to.be.greaterThan(0);
expect(state.keyboardEvent.endCoordinates.screenY).to.be.closeTo(
Dimensions.get('window').height,
10,
);
expect(state.keyboardEvent.endCoordinates.screenX).to.be.equal(0);
}}
/>
</TestSuite>
);
}
function KeyboardEventsView(props: {
autofocus?: boolean;
dismissOnReset?: boolean;
listenToHide?: boolean;
checkIfKeyboardIsVisible?: boolean;
listenToShow?: boolean;
showDismissButton?: boolean;
onSetState: React.Dispatch<
React.SetStateAction<{
keyboardDidShow: boolean;
keyboardDidHide: boolean;
keyboardEvent: KeyboardEvent;
}>
>;
reset: () => void;
}) {
useEffect(() => {
let showSubscription: EmitterSubscription;
let hideSubscription: EmitterSubscription;
if (props.listenToShow) {
showSubscription = Keyboard.addListener('keyboardDidShow', event => {
props.onSetState(prev => ({
...prev,
keyboardEvent: event,
keyboardDidShow: true,
}));
});
}
if (props.listenToHide) {
hideSubscription = Keyboard.addListener('keyboardDidHide', event => {
props.onSetState(prev => ({
...prev,
keyboardEvent: event,
keyboardDidHide: true,
}));
});
}
if (props.checkIfKeyboardIsVisible) {
setTimeout(() => {
if (!Keyboard.isVisible()) {
props.onSetState(prev => ({ ...prev, keyboardDidShow: false }));
}
}, 1000);
}
return () => {
if (props.listenToShow) {
showSubscription.remove();
}
if (props.listenToHide) {
hideSubscription.remove();
}
};
}, []);
return (
<>
<TextInput style={styles.textInput} autoFocus={props.autofocus} />
{props.showDismissButton && (
<Button label={'dismiss keyboard'} onPress={() => Keyboard.dismiss()} />
)}
<Button
label="reset"
onPress={() => {
if (props.dismissOnReset) {
Keyboard.dismiss();
}
props.reset();
}}
/>
</>
);
}
const styles = StyleSheet.create({
textInput: {
borderWidth: 1,
borderColor: 'silver',
backgroundColor: '#444',
height: 32,
borderRadius: 8,
marginTop: 8,
padding: 8,
fontSize: 16,
color: 'white',
},
buttonText: {
width: '100%',
height: '100%',
fontWeight: 'bold',
},
});
export default KeyboardTest;