Skip to content

Commit 068b4d0

Browse files
authored
Dialog and Modal test drivers. (#2893)
* Added drivers for modal and dialog * Added sanity checks with the new drivers * Added dialog dismiss test * Moved TouchableOverlay testID location * Fixed imports. Added ref testing for dismiss * Copied old test with new button driver * Fixed modal test * Added test for modal dismiss * Check onDimiss callback being called
1 parent 090e236 commit 068b4d0

File tree

6 files changed

+181
-3
lines changed

6 files changed

+181
-3
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import {ModalProps} from './index';
2+
import {useComponentDriver, ComponentProps} from '../../testkit/new/Component.driver';
3+
import {usePressableDriver} from '../../testkit/new/usePressable.driver';
4+
5+
export const ModalDriver = (props: ComponentProps) => {
6+
const {renderTree, testID} = props;
7+
const driver = useComponentDriver<ModalProps>(props);
8+
const overlayDriver = usePressableDriver<{}>(useComponentDriver<{}>({renderTree, testID: `${testID}.TouchableOverlay`}));
9+
10+
const isVisible = () => {
11+
return !!driver.getProps().visible;
12+
};
13+
14+
return {...driver, isVisible, pressOnBackground: overlayDriver.press};
15+
};
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import React, {useState} from 'react';
2+
import {render} from '@testing-library/react-native';
3+
import Modal, {ModalProps} from '../';
4+
import {ModalDriver} from '../Modal.driver.new';
5+
import View from '../../view';
6+
import Button from '../../button';
7+
import {ButtonDriver} from '../../button/Button.driver.new';
8+
9+
const testID = 'modal';
10+
11+
const TestCase = (props: Omit<ModalProps, 'testID'>) => {
12+
return <Modal testID={testID} {...props}/>;
13+
};
14+
15+
describe('Sanity modal test', () => {
16+
it('Testing visibility', () => {
17+
const renderTree = render(<TestCase/>);
18+
const modalDriver = ModalDriver({renderTree, testID});
19+
expect(modalDriver.isVisible()).toBeFalsy();
20+
renderTree.rerender(<TestCase visible/>);
21+
expect(modalDriver.isVisible()).toBeTruthy();
22+
});
23+
24+
it('Should press on background', () => {
25+
const backgroundPressHandler = jest.fn();
26+
const renderTree = render(<TestCase visible onBackgroundPress={backgroundPressHandler}/>);
27+
const modalDriver = ModalDriver({renderTree, testID});
28+
expect(backgroundPressHandler).not.toHaveBeenCalled();
29+
modalDriver.pressOnBackground();
30+
expect(backgroundPressHandler).toHaveBeenCalledTimes(1);
31+
});
32+
it('Should dismiss modal', () => {
33+
const onDismissHandler = jest.fn();
34+
const TestCase = () => {
35+
const [showModal, setShowModal] = useState(true);
36+
return (
37+
<View>
38+
<Modal testID={testID} onDismiss={onDismissHandler} visible={showModal}/>
39+
<Button testID={'button-dismiss'} onPress={() => setShowModal(false)}/>
40+
</View>
41+
);
42+
};
43+
const renderTree = render(<TestCase/>);
44+
const modalDriver = ModalDriver({renderTree, testID});
45+
const buttonDriver = ButtonDriver({renderTree, testID: 'button-dismiss'});
46+
expect(modalDriver.isVisible()).toBeTruthy();
47+
expect(onDismissHandler).not.toHaveBeenCalled();
48+
buttonDriver.press();
49+
expect(modalDriver.isVisible()).toBeFalsy();
50+
expect(onDismissHandler).toHaveBeenCalledTimes(1);
51+
});
52+
});

src/components/modal/index.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,10 @@ class Modal extends Component<ModalProps> {
9090
<View
9191
useSafeArea={isScreenReaderEnabled}
9292
style={!isScreenReaderEnabled && [styles.touchableOverlay, {backgroundColor: overlayBackgroundColor}]}
93-
testID={`${testID}.TouchableOverlay`}
9493
>
9594
{/*
9695
// @ts-ignore */}
97-
<TouchableWithoutFeedback {...accessibilityProps} onPress={onBackgroundPress}>
96+
<TouchableWithoutFeedback {...accessibilityProps} onPress={onBackgroundPress} testID={`${testID}.TouchableOverlay`}>
9897
<View style={isScreenReaderEnabled ? styles.accessibleOverlayView : styles.fill}/>
9998
</TouchableWithoutFeedback>
10099
</View>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import {DialogProps} from './index';
2+
import {useComponentDriver, ComponentProps} from '../../testkit/new/Component.driver';
3+
import {ModalDriver} from '../../testkit/';
4+
5+
export const DialogDriver = (props: ComponentProps) => {
6+
const {renderTree, testID} = props;
7+
const driver = useComponentDriver<DialogProps>(props);
8+
const modalDriver = ModalDriver({renderTree, testID: `${testID}.modal`});
9+
return {...modalDriver, ...driver};
10+
};
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import React, {useRef, useState, useEffect, useCallback} from 'react';
2+
import {render, act} from '@testing-library/react-native';
3+
import Dialog, {DialogProps} from '../index';
4+
import {DialogDriver} from '../Dialog.driver.new';
5+
import View from '../../../components/view';
6+
import Button from '../../../components/button';
7+
import {ButtonDriver} from '../../../components/button/Button.driver.new';
8+
9+
const testID = 'dialog';
10+
11+
const TestCase1 = (props: Omit<DialogProps, 'testID'>) => {
12+
return <Dialog testID={testID} {...props}/>;
13+
};
14+
15+
const onDismiss = () => {};
16+
17+
const defaultProps = {
18+
testID: 'dialog',
19+
useSafeArea: true,
20+
onDismiss,
21+
bottom: true,
22+
centerH: true
23+
};
24+
25+
const TestCase2 = props => {
26+
const [visible, setVisible] = useState(props.visible);
27+
28+
useEffect(() => {
29+
setVisible(props.visible);
30+
}, [props.visible]);
31+
32+
const openDialog = useCallback(() => {
33+
setVisible(true);
34+
}, []);
35+
36+
const closeDialog = useCallback(() => {
37+
setVisible(false);
38+
}, []);
39+
40+
return (
41+
<View>
42+
<Dialog {...defaultProps} {...props} visible={visible}>
43+
<View height={300}>
44+
<Button testID={'closeButton'} flex onPress={closeDialog}/>
45+
</View>
46+
</Dialog>
47+
<Button testID={'openButton'} flex onPress={openDialog}/>
48+
</View>
49+
);
50+
};
51+
52+
const getDriver = (Element: React.JSX.Element) => {
53+
const renderTree = render(Element);
54+
const dialogDriver = DialogDriver({renderTree, testID});
55+
return {renderTree, dialogDriver};
56+
};
57+
58+
describe('Incubator.Dialog sanity checks', () => {
59+
it('Should show dialog', () => {
60+
const {dialogDriver} = getDriver(<TestCase1 visible/>);
61+
expect(dialogDriver.isVisible()).toBeTruthy();
62+
});
63+
64+
it('Should dismiss dialog on background press', () => {
65+
const dismissFn = jest.fn();
66+
const {dialogDriver} = getDriver(<TestCase1 visible onDismiss={dismissFn}/>);
67+
expect(dismissFn).not.toHaveBeenCalled();
68+
expect(dialogDriver.isVisible()).toBeTruthy();
69+
dialogDriver.pressOnBackground();
70+
expect(dialogDriver.isVisible()).toBeFalsy();
71+
expect(dismissFn).toHaveBeenCalledTimes(1);
72+
});
73+
74+
it('Should dismiss dialog on dismiss call', () => {
75+
let dialogRef: React.RefObject<{dismiss: () => void}>;
76+
const RefTestCase = () => {
77+
dialogRef = useRef<{dismiss:() => void}>(null);
78+
return <Dialog testID={testID} visible ref={dialogRef}/>;
79+
};
80+
const {dialogDriver} = getDriver(<RefTestCase/>);
81+
expect(dialogDriver.isVisible()).toBeTruthy();
82+
act(() => {
83+
dialogRef.current?.dismiss();
84+
});
85+
expect(dialogDriver.isVisible()).toBeFalsy();
86+
});
87+
it('Should exist only if visible', async () => {
88+
const onDismiss = jest.fn();
89+
const component = <TestCase2 onDismiss={onDismiss}/>;
90+
const {dialogDriver, renderTree} = getDriver(component);
91+
expect(dialogDriver.exists()).toBeFalsy();
92+
const openButtonDriver = ButtonDriver({renderTree, testID: 'openButton'});
93+
await openButtonDriver.press();
94+
expect(await dialogDriver.exists()).toBeTruthy();
95+
expect(onDismiss).toHaveBeenCalledTimes(0);
96+
const closeButtonDriver = ButtonDriver({renderTree, testID: 'closeButton'});
97+
await closeButtonDriver.press();
98+
expect(await dialogDriver.exists()).toBeFalsy();
99+
expect(onDismiss).toHaveBeenCalledTimes(1);
100+
});
101+
});

src/testkit/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ export {useComponentDriver, ComponentProps} from './new/Component.driver';
22
export {usePressableDriver} from './new/usePressable.driver';
33
export {useScrollableDriver} from './new/useScrollable.driver';
44
export {useDraggableDriver} from './new/useDraggable.driver';
5-
65
export {CarouselDriver} from '../components/carousel/Carousel.driver.new';
76
export {CheckboxDriver} from '../components/checkbox/Checkbox.driver';
87
export {SortableListDriver} from '../components/sortableList/SortableList.driver.new';
98
export {SortableListItemDriver} from '../components/sortableList/SortableListItem.driver.new';
109
export {TextDriver} from '../components/text/Text.driver.new';
1110
export {TextFieldDriver} from '../components/textField/TextField.driver.new';
1211
export {ViewDriver} from '../components/view/View.driver.new';
12+
export {ModalDriver} from '../components/modal/Modal.driver.new';
13+
export {DialogDriver} from '../incubator/Dialog/Dialog.driver.new';
1314
export {ButtonDriver} from '../components/button/Button.driver.new';
1415
export {ImageDriver} from '../components/image/Image.driver.new';
1516
export {SwitchDriver} from '../components/switch/switch.driver';

0 commit comments

Comments
 (0)