Skip to content

Dialog and Modal test drivers. #2893

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/components/modal/Modal.driver.new.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {ModalProps} from './index';
import {useComponentDriver, ComponentProps} from '../../testkit/new/Component.driver';
import {usePressableDriver} from '../../testkit/new/usePressable.driver';

export const ModalDriver = (props: ComponentProps) => {
const {renderTree, testID} = props;
const driver = useComponentDriver<ModalProps>(props);
const overlayDriver = usePressableDriver<{}>(useComponentDriver<{}>({renderTree, testID: `${testID}.TouchableOverlay`}));

const isVisible = () => {
return !!driver.getProps().visible;
};

return {...driver, isVisible, pressOnBackground: overlayDriver.press};
};
52 changes: 52 additions & 0 deletions src/components/modal/__test__/index.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React, {useState} from 'react';
import {render} from '@testing-library/react-native';
import Modal, {ModalProps} from '../';
import {ModalDriver} from '../Modal.driver.new';
import View from '../../view';
import Button from '../../button';
import {ButtonDriver} from '../../button/Button.driver.new';

const testID = 'modal';

const TestCase = (props: Omit<ModalProps, 'testID'>) => {
return <Modal testID={testID} {...props}/>;
};

describe('Sanity modal test', () => {
it('Testing visibility', () => {
const renderTree = render(<TestCase/>);
const modalDriver = ModalDriver({renderTree, testID});
expect(modalDriver.isVisible()).toBeFalsy();
renderTree.rerender(<TestCase visible/>);
expect(modalDriver.isVisible()).toBeTruthy();
});

it('Should press on background', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test close when background is pressed

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or Should dismiss modal on background press

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually don't think this causes the modal to dismiss it just lets you press on the background. On the dialog pressing on the background of the modal makes it dismiss.

const backgroundPressHandler = jest.fn();
const renderTree = render(<TestCase visible onBackgroundPress={backgroundPressHandler}/>);
const modalDriver = ModalDriver({renderTree, testID});
expect(backgroundPressHandler).not.toHaveBeenCalled();
modalDriver.pressOnBackground();
expect(backgroundPressHandler).toHaveBeenCalledTimes(1);
});
it('Should dismiss modal', () => {
const onDismissHandler = jest.fn();
const TestCase = () => {
const [showModal, setShowModal] = useState(true);
return (
<View>
<Modal testID={testID} onDismiss={onDismissHandler} visible={showModal}/>
<Button testID={'button-dismiss'} onPress={() => setShowModal(false)}/>
</View>
);
};
const renderTree = render(<TestCase/>);
const modalDriver = ModalDriver({renderTree, testID});
const buttonDriver = ButtonDriver({renderTree, testID: 'button-dismiss'});
expect(modalDriver.isVisible()).toBeTruthy();
expect(onDismissHandler).not.toHaveBeenCalled();
buttonDriver.press();
expect(modalDriver.isVisible()).toBeFalsy();
expect(onDismissHandler).toHaveBeenCalledTimes(1);
});
});
Comment on lines +32 to +52
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a test for the dismiss callback.

3 changes: 1 addition & 2 deletions src/components/modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,10 @@ class Modal extends Component<ModalProps> {
<View
useSafeArea={isScreenReaderEnabled}
style={!isScreenReaderEnabled && [styles.touchableOverlay, {backgroundColor: overlayBackgroundColor}]}
testID={`${testID}.TouchableOverlay`}
>
{/*
// @ts-ignore */}
<TouchableWithoutFeedback {...accessibilityProps} onPress={onBackgroundPress}>
<TouchableWithoutFeedback {...accessibilityProps} onPress={onBackgroundPress} testID={`${testID}.TouchableOverlay`}>
<View style={isScreenReaderEnabled ? styles.accessibleOverlayView : styles.fill}/>
</TouchableWithoutFeedback>
</View>
Expand Down
10 changes: 10 additions & 0 deletions src/incubator/Dialog/Dialog.driver.new.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {DialogProps} from './index';
import {useComponentDriver, ComponentProps} from '../../testkit/new/Component.driver';
import {ModalDriver} from '../../testkit/';

export const DialogDriver = (props: ComponentProps) => {
const {renderTree, testID} = props;
const driver = useComponentDriver<DialogProps>(props);
const modalDriver = ModalDriver({renderTree, testID: `${testID}.modal`});
return {...modalDriver, ...driver};
};
101 changes: 101 additions & 0 deletions src/incubator/Dialog/__tests__/index.new.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import React, {useRef, useState, useEffect, useCallback} from 'react';
import {render, act} from '@testing-library/react-native';
import Dialog, {DialogProps} from '../index';
import {DialogDriver} from '../Dialog.driver.new';
import View from '../../../components/view';
import Button from '../../../components/button';
import {ButtonDriver} from '../../../components/button/Button.driver.new';

const testID = 'dialog';

const TestCase1 = (props: Omit<DialogProps, 'testID'>) => {
return <Dialog testID={testID} {...props}/>;
};

const onDismiss = () => {};

const defaultProps = {
testID: 'dialog',
useSafeArea: true,
onDismiss,
bottom: true,
centerH: true
};

const TestCase2 = props => {
const [visible, setVisible] = useState(props.visible);

useEffect(() => {
setVisible(props.visible);
}, [props.visible]);

const openDialog = useCallback(() => {
setVisible(true);
}, []);

const closeDialog = useCallback(() => {
setVisible(false);
}, []);

return (
<View>
<Dialog {...defaultProps} {...props} visible={visible}>
<View height={300}>
<Button testID={'closeButton'} flex onPress={closeDialog}/>
</View>
</Dialog>
<Button testID={'openButton'} flex onPress={openDialog}/>
</View>
);
};

const getDriver = (Element: React.JSX.Element) => {
const renderTree = render(Element);
const dialogDriver = DialogDriver({renderTree, testID});
return {renderTree, dialogDriver};
};

describe('Incubator.Dialog sanity checks', () => {
it('Should show dialog', () => {
const {dialogDriver} = getDriver(<TestCase1 visible/>);
expect(dialogDriver.isVisible()).toBeTruthy();
});

it('Should dismiss dialog on background press', () => {
const dismissFn = jest.fn();
const {dialogDriver} = getDriver(<TestCase1 visible onDismiss={dismissFn}/>);
expect(dismissFn).not.toHaveBeenCalled();
expect(dialogDriver.isVisible()).toBeTruthy();
dialogDriver.pressOnBackground();
expect(dialogDriver.isVisible()).toBeFalsy();
expect(dismissFn).toHaveBeenCalledTimes(1);
});

it('Should dismiss dialog on dismiss call', () => {
let dialogRef: React.RefObject<{dismiss: () => void}>;
const RefTestCase = () => {
dialogRef = useRef<{dismiss:() => void}>(null);
return <Dialog testID={testID} visible ref={dialogRef}/>;
};
const {dialogDriver} = getDriver(<RefTestCase/>);
expect(dialogDriver.isVisible()).toBeTruthy();
act(() => {
dialogRef.current?.dismiss();
});
expect(dialogDriver.isVisible()).toBeFalsy();
});
it('Should exist only if visible', async () => {
const onDismiss = jest.fn();
const component = <TestCase2 onDismiss={onDismiss}/>;
const {dialogDriver, renderTree} = getDriver(component);
expect(dialogDriver.exists()).toBeFalsy();
const openButtonDriver = ButtonDriver({renderTree, testID: 'openButton'});
await openButtonDriver.press();
expect(await dialogDriver.exists()).toBeTruthy();
expect(onDismiss).toHaveBeenCalledTimes(0);
const closeButtonDriver = ButtonDriver({renderTree, testID: 'closeButton'});
await closeButtonDriver.press();
expect(await dialogDriver.exists()).toBeFalsy();
expect(onDismiss).toHaveBeenCalledTimes(1);
});
});
3 changes: 2 additions & 1 deletion src/testkit/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ export {useComponentDriver, ComponentProps} from './new/Component.driver';
export {usePressableDriver} from './new/usePressable.driver';
export {useScrollableDriver} from './new/useScrollable.driver';
export {useDraggableDriver} from './new/useDraggable.driver';

export {CarouselDriver} from '../components/carousel/Carousel.driver.new';
export {CheckboxDriver} from '../components/checkbox/Checkbox.driver';
export {SortableListDriver} from '../components/sortableList/SortableList.driver.new';
export {SortableListItemDriver} from '../components/sortableList/SortableListItem.driver.new';
export {TextDriver} from '../components/text/Text.driver.new';
export {TextFieldDriver} from '../components/textField/TextField.driver.new';
export {ViewDriver} from '../components/view/View.driver.new';
export {ModalDriver} from '../components/modal/Modal.driver.new';
export {DialogDriver} from '../incubator/Dialog/Dialog.driver.new';
export {ButtonDriver} from '../components/button/Button.driver.new';
export {ImageDriver} from '../components/image/Image.driver.new';
export {SwitchDriver} from '../components/switch/switch.driver';