给出以下代码:
import { Keyboard } from 'react-native';
// ....
componentDidMount() {
this.keyboardShowListener = Keyboard.addListener(
'keyboardWillShow',
() => this.setState({ visible: true }),
);
this.keyboardHideListener = Keyboard.addListener(
'keyboardWillHide',
() => this.setState({ visible: false }),
);
}
// ....
onCancel() {
const { clearActiveInput } = this.props;
clearActiveInput();
Keyboard.dismiss();
}
是否有一种模拟导入的Keyboard
组件的正确方法,既可以验证侦听器订阅是否已发生,又可以验证dismiss()
事件是否已触发?
答案 0 :(得分:3)
所以这个问题比我想像中要解决的复杂得多。 既然您要在这里测试的是基本上针对键盘的dismiss()和show()呢?
因此,文档中0.63和0.62的事件和侦听器为https://reactnative.dev/docs/keyboard#docsNav
useEffect(() => {
Keyboard.addListener("keyboardDidShow", _keyboardDidShow);
Keyboard.addListener("keyboardDidHide", _keyboardDidHide);
// cleanup function
return () => {
Keyboard.removeListener("keyboardDidShow", _keyboardDidShow);
Keyboard.removeListener("keyboardDidHide", _keyboardDidHide);
};
}, []);
const _keyboardDidShow = () => {
alert("Keyboard Shown");
};
const _keyboardDidHide = () => {
alert("Keyboard Hidden");
};
要使Jest调用两个函数_keyboardDidShow
和_keyboardDidHide
,您将需要使用Keyboard.emit('_keyboardDidShow')
示例:
it('Test Keyboards keyboardDidShow is called', () => {
const { getByTestId } = render(<Container />);
act(() => {
Keyboard.emit('keyboardDidShow', {});
});
const box = getByTestId('TEST');
//Do here your expect clauses to check if something changed in your container
});
不完全确定这是否能帮助任何人。但这就是我解决这个难题的方法,以弄清楚如何覆盖_keyboardDidShow和Hide
答案 1 :(得分:1)
我在订阅Keyboard
事件的组件中也遇到了类似的问题
const MyComponent = () => {
useEffect(() => {
const listener = Keyboard.addListener('keyboardDidHide', () => {})
return () => {
listener.remove()
}
})
return <View>...</View>
}
我可以通过以下测试来测试Keyboard.addListener
,还可以测试组件卸载后正在调用listener.remove
import renderer from 'react-test-renderer'
const mockListener = {
remove: jest.fn(),
}
const originalAddListener = Keyboard.addListener
const mockAddListener = jest.fn().mockReturnValue(mockListener)
describe('<MyComponent />', () => {
beforeAll(() => {
Keyboard.addListener = mockAddListener
})
beforeEach(() => {
mockAddListener.mockClear()
mockListener.remove.mockClear()
})
afterAll(() => {
Keyboard.addListener = originalAddListener
})
it('should subscribe to KeyboardDidClose event', () => {
render(<MyComponent />)
expect(Keyboard.addListener).toHaveBeenCalled()
})
it('should call listener.remove on unmount', () => {
const component = render(
< MyComponent />,
)
component.unmount()
expect(mockListener.remove).toHaveBeenCalled()
})
})
答案 2 :(得分:0)
编辑:请使用@Thiago de Oliveira Cruz 提供的方法,该方法更简洁、更易于使用。
我使用 this article 中提到的方法来“触发”'keyboardDidShow'
和 'keyboardDidHide'
事件。基本上,我们模拟实现 keyboard.addListener
并使用映射来记录事件到回调的映射。这样,在安装组件后,我们就可以访问与 'keyboardDidShow'
和 'keyboardDidHide'
事件关联的回调。然后我们直接调用回调函数,就好像事件已经被触发一样。
这显然是一种解决方法,但它适用于我的用例。下面是一个简单的示例,说明如何测试使用 'keyboardDidShow'
和 'keyboardDidHide'
事件来控制是否显示一段文本的组件。有关示例的详细说明,请参阅 here。
import * as React from 'react';
import {View, Text, Keyboard} from 'react-native';
const MyComponent = () => {
const [showText, setShowText] = React.useState(true);
// Use keyboard event (https://reactnative.dev/docs/keyboard)
React.useEffect(() => {
Keyboard.addListener('keyboardDidShow', _keyboardDidShow);
Keyboard.addListener('keyboardDidHide', _keyboardDidHide);
// cleanup function
return () => {
Keyboard.removeListener('keyboardDidShow', _keyboardDidShow);
Keyboard.removeListener('keyboardDidHide', _keyboardDidHide);
};
}, []);
const _keyboardDidShow = () => setShowText(false);
const _keyboardDidHide = () => setShowText(true);
if (showText) {
return (
<View>
<Text>Bear, Beets, Battlestar Galactica</Text>
</View>
);
}
return null;
};
export {MyComponent};
import * as React from 'react';
import {Keyboard} from 'react-native';
import {mount} from 'enzyme';
import {MyComponent} from 'mycomponent.js';
describe('Test MyComponent', () => {
const mockSetShowText = jest.fn();
const mockUseState = jest.spyOn(React, 'useState');
const mockKeyboardListener = jest.spyOn(Keyboard, 'addListener');
const keyboardCallbackMap = {};
afterAll(() => {
mockSetShowText.mockReset();
mockKeyboardListener.mockRestore();
mockUseState.mockRestore();
});
test('Text shown by default', () => {
const myComponent = mount(<MyComponent />);
expect(myComponent.find('Text').first()).toHaveText(
'Bear, Beets, Battlestar Galactica',
);
});
test('Text not show when showText is false', () => {
mockUseState.mockReturnValue([false, mockSetShowText]);
const myComponent = mount(<MyComponent />);
expect(myComponent.find('Text')).not.toExist();
});
test('When Keyboard shows up, set showText to false; when disappear, set showText to true', () => {
mockKeyboardListener.mockImplementation((event, cb) => {
keyboardCallbackMap[event] = cb;
});
mockUseState.mockImplementation(showText => [showText, mockSetShowText]);
const myComponent = mount(<MyComponent />);
keyboardCallbackMap.keyboardDidShow(); // mock keyboardDidShow event
expect(mockSetShowText).toHaveBeenCalledWith(false);
keyboardCallbackMap.keyboardDidHide(); // mock keyboardDidHide event
expect(mockSetShowText).toHaveBeenCalledWith(true);
myComponent.unmount();
});
});